我目前正在开发EF Fluent项目(是的,我喜欢这样写),这是在EF 4.3上使用Table-Per-Type架构的模型第一种方法。
正如我在过去几个月发现的那样,Table-Per-Type和继承只是不太好 - > more information。我正在使用一个带有七个派生类的基类,只是在七个派生类中返回项目并不是特别快。在执行时间方面,要检索五个记录的列表EF需要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')运行这样的东西返回所有派生在一次数据库命中中排序的结果集......
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;
但是,这不适用于InvalidOperationException,抱怨CommandText无效且我必须提供'ContainerName'。我在这里猜测,如果我使用EDMX文件,我可以设置此设置项(并使用DefaultContainerName不起作用)。但是我采取了流利的方法,我觉得我已经走到了尽头。
因此...
有哪些方法可以解决EF和table-per-type的性能问题? 是否可以通过具有Fluent / Model First方法的ObjectContext执行存储过程? 我可以执行标准的SQLClient.SqlDataReader并转换为ObjectContext吗?
提前致谢...
答案 0 :(得分:1)
好的 - 似乎ObjectContext可以从System.Data.SqlClient.SqlDataReader转换,这意味着我不需要从dbContext派生(直接)。这是示例代码......
IList<MyBaseClass> items = new List<MyBaseClass>();
ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext;
using (var sqlConn = new SqlConnection(dbContext.Database.Connection.ConnectionString))
{
SqlCommand sqlComm = new SqlCommand(){
Connection = sqlConn,
CommandText = "spGetMyDerivedItems",
CommandType = CommandType.StoredProcedure
};
sqlConn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach( x => items.Add(x));
reader.NextResult();
...repeat for each derived type...
}
}
return items;
显然最好的答案是EF会选择这个,但我现在对上述情况感到满意。移动到EF5听起来是一个很好的举动 - 但是有了不同的时间尺度,你知道的魔鬼会更好:)
感谢您的帮助。