如何为通用数据库方法创建商业模型封装?

3
我目前在使用Entity Framework 4作为OR-Mapper从我的数据库中创建POCO对象时遇到了性能问题。整个应用程序现在是一个原型。
假设我想要一些业务对象,比如类“Printer”或“Scanner”。这两个类都继承自一个名为Product的基类。这些业务类已经存在。
我尝试使用更通用的数据库方法。我不想为“Printer”或“Scanner”创建表格。我想要有3个表:一个叫做Product,另外两个是Property和PropertyValue(它们存储分配给特定产品的所有值)。
在我的业务层中,我会像这样创建一个特定的对象:
public Printer GetPrinter(int IDProduct)
{
  Printer item = new Printer();
  // get the product object with EF
  // get all PropertyValues
  // (with Reflection) foreach property in item.GetType().GetProperties
  // {
  //   property.SetValue("specific value")
  // }
  return item;
}

这是EF模型的样子: enter image description here 目前为止运行良好,我正在进行检索多个集合的性能测试。
我创建了一个原型并进行了多次改进以提高性能。但它离可用还有很长的路要走。 创建300个仅包含3个属性的对象需要919毫秒。
选择这种数据库设计的原因是为了拥有通用的数据库设计。添加新属性应该只在业务模型中完成。
我是不是太愚蠢了,无法创建一个高效的检索xx对象的方法,或者我的方法完全错误?就我所了解的ORM映射器,它们基本上都是做同样的事情吗?

你的方法中同时使用了反射和元表 - 这些技术都会降低性能。不如创建具体的类来看看它的性能如何? - rsenna
@rsenna:您的意思是通过元表将数据库行映射到EF类型中? - citronas
PropertyPropertyValue 是元表。它们并不直接映射到实际的业务实体,而是用于通用地定义新的“类型”实体及其相关值。我同意这种方法很强大(有时非常有用),但你肯定会在性能上付出代价。 - rsenna
2个回答

5
我认为你错过了ORM的全部要点。人们使用ORM的原因是为了能够持久化业务对象并轻松地检索业务对象。你正在使用ORM仅获取业务对象工厂所需的数据。工厂使用反射从ORM检索到的实例化类构建业务对象。这将始终非常缓慢,因为:
  • 查询编译很慢(可以预编译)
  • 对象实例化很慢(无法避免)
  • 反射很慢(无法避免)
如果您想遵循此数据库设计,使其绝对独立于您的业务对象,则不需要ORM,或者至少不需要EF。
你的性能问题的原因在于你的业务模型没有遵循通用方法。因此,您必须在某个地方将通用数据转换为特定数据=缓慢操作。
如果您想提高性能,请定义一组共享属性并将它们放入Product中。然后,使用当前PropertyValue和Property来获取其他非共享属性,或者使用简单的ExtendedProperties表存储键值对。您的实体将是类型为Product的内部类型属性、共享属性和扩展属性集合。这就是通用方法。

好的,说得有道理。但是如果我想在“通用”的数据库中保留这个想法,而不需要为每个属性手动编写映射器,该怎么办呢?你是建议我使用 SQL 查询吗? - citronas
我已经添加了一些建议。这不是一个好的方法,但如果你想保持通用存储并提高性能,就必须避免使用反射。 - Ladislav Mrnka
我决定以这种方式构建我的数据库,即我不需要通过反射获取超过一个或两个项目。我决定将公共属性放在产品表内,并将它们用于列表形式的表示。反射部分仅用于显示详细信息。 - citronas

1
首先,我不清楚您拥有哪些POCO。您是手动编写它们和上下文还是使用T4生成的?这里有一些很棒的文章here,可以对没有POCO、T4生成的POCO/上下文和手动编写的POCO/上下文进行性能基准测试。如预期的那样,选择POCO路线可以获得巨大的性能提升(在他的基准测试中,性能提升超过15倍),而不是使用Entity Framework生成的POCO。如果您使用的是MSSQL,请打开分析器并查看正在生成什么?

手工编码。我相对较新地开始使用EF4的强大功能。我看到的问题是,POCO生成(无论是通过T4还是EF本身)都基于表结构,并且不可能实现这样的映射(从Product表和PropertyValue创建一个Product的POCO)。或者我错了吗? - citronas
请参考上面Ladislav的评论,我完全同意。 - Bayrat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接