每种类型性能的实体框架表

时间:2011-01-09 23:03:44

标签: entity-framework inheritance .net-3.5 table-per-type

事实证明,在实现TPT(每种类型的表)继承时,我是发现微软实体框架中存在的基础底层的最后一个人。

构建了一个包含3个子类的原型,包含20多列的基表/类和包含~10列的子表,一切都运行得很漂亮,我继续研究其余的应用程序,证明了这个概念。现在是添加其他20个子类型和OMG的时候了,我刚刚开始查看在简单选择上生成的SQL,即使我只对访问基类上的字段感兴趣。

This page对问题进行了精彩描述。

有没有人使用TPT和EF投入生产,是否有任何变通办法,这意味着我不必: a)将模式转换为TPH(这与我尝试用我的数据库设计实现的所有内容相反 - urrrgghh!)? b)用另一个ORM重写?

我看到它的方式,我应该能够在EF(可能使用EFExtensions)中添加对存储过程的引用,该存储过程具有仅选择我需要的字段的TSQL,即使使用EF生成的代码也是如此SP内部的怪物UNION / JOIN会阻止每次调用时生成SQL - 这不是我打算做的事情,但是你明白了。

我发现的杀手是,当我选择链接到基表的实体列表时(但我选择的实体不是子类表),我想按pk过滤Base表,我.Include("BaseClassTableName")允许我使用x=>x.BaseClass.PK == 1进行过滤并访问其他属性,它也在这里执行母SQL生成。

我无法使用EF4,因为我仅限于安装了3.5 SP1的.net 2.0运行时。

有没有人有过摆脱这种混乱的经历?

2 个答案:

答案 0 :(得分:2)

我们遇到了同样的问题,并且正在考虑将我们的DAL从EF4移植到LLBLGen因此。

与此同时,我们使用编译查询来缓解一些痛苦:

Compiled Queries (LINQ to Entities)

此策略不会阻止庞大的查询,但生成查询所需的时间(可能很大)只执行一次。

你可以使用带有Includes()的编译查询:

static readonly Func<AdventureWorksEntities, int, Subcomponent> subcomponentWithDetailsCompiledQuery = CompiledQuery.Compile<AdventureWorksEntities, int, Subcomponent>(
       (ctx, id) => ctx.Subcomponents
            .Include("SubcomponentType")
            .Include("A.B.C.D")
            .FirstOrDefault(s => s.Id == id));

    public Subcomponent GetSubcomponentWithDetails(int id)
    {
        return subcomponentWithDetailsCompiledQuery.Invoke(ObjectContext, id);
    }

答案 1 :(得分:1)

这似乎有点困惑。你在谈论TPH,但当你说:

  

我看到它的方式,我应该能够在EF(可能使用EFExtensions)中添加对存储过程的引用,该存储过程具有仅选择我需要的字段的TSQL,即使使用EF生成的代码也是如此SP内部的怪物UNION / JOIN会阻止每次调用时生成SQL - 这不是我打算做的事情,但是你明白了。

那么,这是每个具体类映射的表(使用proc而不是表,但仍然是映射是TPC ......)。 EF支持TPC,但设计师没有。 You can do it in code-first if you get the CTP

如果限制查询,首选的使用proc的解决方案将导致性能问题,如下所示:

var q = from c in Context.SomeChild
        where c.SomeAssociation.Foo == foo
        select c;

数据库优化器无法查看proc实现,因此您可以全面扫描结果。

因此,在您告诉自己这将修复您的结果之前,请仔细检查该假设。

请注意,您始终可以使用ObjectContext.ExecuteStoreQuery任何映射策略指定自定义SQL。

但是,在执行任何此操作之前,请考虑一下,正如RPM1984指出的那样,您的设计似乎过度使用了继承。我喜欢this quote from NHibernate in Action

  

[A]了解自己是否可以更好地将继承重建为对象模型中的委托。由于与持久性或ORM无关的各种原因,通常可以最好地避免复杂继承。 [您的ORM]充当对象和关系模型之间的缓冲区,但这并不意味着您在设计对象模型时可以完全忽略持久性问题。