Entity Framework Fluent,Table-Per-Type性能替代方案

时间:2013-02-07 18:34:14

标签: c# .net entity-framework entity-framework-4 fluent

我目前正在开发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吗?

提前致谢...

1 个答案:

答案 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听起来是一个很好的举动 - 但是有了不同的时间尺度,你知道的魔鬼会更好:)

感谢您的帮助。