实体框架4.2表每层次组由discriminator



我正在做一个使用EF 4.2代码优先模型的项目。该模型包含产品的TPH继承结构。我需要在鉴别器上对这个继承模型的多态结果进行分组,并且遇到了一些问题。

实体框架没有公开鉴别符来完成这个分组。我的第一个问题是我可以直接访问这个鉴别器吗?我的阅读和经验告诉我不能,所以我想出了这个解决方案。它的性能不太好,我对它需要如何维护感到不满意。

我的类看起来像这样(简化):

Public MustInherit Class Product
      <key()>  
      Public Property ProductID as integer
      <StringLength(50, ErrorMessage:="Max 50 characters")>
      <Required(ErrorMessage:="Product name is required")>
      Public Property Name as String
      <TimeStamp()>
      Public Property Time_Stamp as DateTime = DateTime.Now()
End Class
Public Class Desktop
      Inherits Product
      <StringLength(50, ErrorMessage:="Max 50 characters")>
      <Required(ErrorMessage:="Processor is required")>
      Public Property Processor as String
End Class
Public Class Monitor
      Inherits Product
      <Required(ErrorMessage:="Monitor size is required")>
      Public Property Size_Inches as Integer
End Class

我构建了一个扩展方法,它接受一个product,并以字符串形式返回它的基类型名称。

<Extension()>
Public Function ProductType(ByVal inProduct as Product) as String
      ProductType = inProduct.GetType().BaseType.Name
End Function

然后,我构建了这个结构,将product的结果按类型分组,以便我可以遍历它们:

Dim tmpProducts = db.Products.ToList()
Dim GrpProducts = tmpProducts.GroupBy(Function(prod) prod.ProductType) _
                             .Select(Function(s) New With {.ProductType = S.Key,
                                                           .Products = S })

我现在可以遍历列表以获得我想要的行为,但性能并不理想,我担心随着产品数量的增长,它将是不可接受的。

For Each ProductGroup in GrpProducts
       Dim TypeName as String = ProductGroup.ProductType
       Dim TypeProducts = ProductGroup.Products
Next

同样,这可以让我很容易地访问共享属性(Name),但现在我没有太多的选项来将这些属性转换为它们的实际类型,也许在TypeName周围有一个select case…

任何建议都是赞赏的,也请原谅上面的任何代码错误,我从记忆中重新键入的例子,因为我目前没有访问该项目。

一个解决方案是建立更多的模型,并有一个具有属性Name的新实体ProductType。然后你会得到ProductProductType之间简单的1-N关系。我没有使用EntityFramework,但是使用NHibernate,您可以轻松地使框架在查询时始终连接该表,这样它就不会为每个Product返回ProductType的代理,这可能会损害性能。

作为一个附加组件,将来ProductType可以开发其他有趣的属性(例如对于该ProductType的每个Product都通用的值),因此它为您的解决方案增加了灵活性,尽管它确实需要立即向数据库添加另一个表。

下面的Linq查询将为您提供一种解决group by discriminator的方法

from a in db.Records
group a.ID by new
{
    Name= a is Audio ? "Audio" :
            a is Video ? "Video" :
            a is Picture ? "Picture" :
            a is Document ? "Document" : "File"
} into g
select new 
{
    Name = g.Key.Name,
    Total = g.Count()
}

最新更新