【发布时间】:2013-02-07 18:34:13
【问题描述】:
我目前正在开发一个 EF Fluent 项目(是的,我确实喜欢这样编写它),该项目在 EF 4.3 上采用模型优先方法,采用 Table-Per-Type 架构。
正如我在过去几个月中发现的那样,Table-Per-Type 和继承并不能很好地发挥作用 -> more information。我正在使用具有七个派生类的单个基类,并且仅在七个派生类中返回项目并不是特别快。在执行时间方面,EF 检索包含 5 条记录的列表需要 5 到 7 秒,随后的执行大约需要 2.5 到 4 秒。可以肯定地说这是不可接受的,所以我正在寻找替代方法......
我能做的是多次访问数据库,即尝试检索每种类型的对象个体并整理成一个集合;但是,该代码充其量是笨拙的,即
IList<MyBaseClass> items = new List<MyBaseClass>();
dbContext.Database.SqlQuery<MyFirstDerivedClass>("SELECT * FROM MyBaseClass INNER JOIN MyFirstDerivedClass ON...").ToList().ForEach(x => items.Add(x));
... repeat for each derived class...
return items;
但它有效!对数据库的第一次点击需要 2 秒,随后的查询只需 200 毫秒。
我的问题是这不是很优雅、可维护等等。我一直在玩弄将 dbContext 转换为 ObjectContext 并使用类似这样的存储过程('spGetMyDerivedItems')运行返回所有派生的结果集在一个 db hit 中排序...
IList<MyBaseClass> items = new List<MyBaseClass>();
ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext;
using (var connection = oContext.Connection as EntityConnection)
{
EntityCommand command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "spGetMyDerivedItems";
connection.Open();
using (EntityDataReader reader = command.ExecuteReader())
{
oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach( x => items.Add(x));
reader.NextResult();
...repeat for each derived type...
}
}
return items;
但是,这不适用于抱怨 CommandText 无效并且我必须提供“ContainerName”的 InvalidOperationException。我在这里的猜测是,如果我使用的是 EDMX 文件,我可以设置这个设置项(并且使用 DefaultContainerName 不起作用)。但是我正在采取一种流利的方法,我觉得我已经走到了死胡同。
所以...
有哪些方法可以解决 EF 和 table-per-type 的性能问题? 是否可以使用 Fluent / Model First 方法通过 ObjectContext 执行存储过程? 我可以执行标准 SQLClient.SqlDataReader 并转换为 ObjectContext 吗?
提前谢谢...
【问题讨论】:
-
这可能不是您正在寻找的答案,所以我在这里只留下评论和一些参考:根据声明,在 EF 5/.NET 4.5 TPT 性能已“显着提高”这里:data.uservoice.com/forums/… 另一方面,EF 团队仍然不鼓励在这里使用 TPT:msdn.microsoft.com/en-us/data/hh949853.aspx 我不知道以秒或毫秒为单位的改进意味着什么。
-
通常 SQL 生成质量和性能(特别是由于在 EF 5/.NET 4.5 中默认使用已编译查询)已得到改进:blogs.msdn.com/b/adonet/archive/2012/02/14/… 和 outofmemory.co.uk/… 改进的 TPT 可能受益于两者.
-
只是出于好奇,为什么不使用 table-per-inheritance?
-
我认为 .NET 4.5 的改进主要基于查询基本类型或使用
OfType+ 自动编译查询。如果要查询所有类型,EF 仍然必须生成具有大量连接的复杂查询,并且性能会很差。 -
Josh - 不幸的是,我正在挑选这个项目,而不是自己构建它。 Slauma - 很高兴听到有一些改进,我们当前的开发阶段将使用以下解决方案运行,但我肯定会升级!
标签: c# .net entity-framework entity-framework-4 fluent