2

我目前正在开发一个 EF Fluent 项目(是的,我确实喜欢这样写),该项目在 EF 4.3 上采用模型优先的方法,采用 Table-Per-Type 架构。

正如我在过去几个月中发现的那样,Table-Per-Type 和继承并不能很好地发挥作用 ->更多信息。我正在使用具有七个派生类的单个基类,并且仅在七个派生类中返回项目并不是特别快。在执行时间方面,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')运行,返回所有排序的派生结果集一分贝命中...

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 吗?

提前致谢...

4

1 回答 1

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 听起来是个不错的举措 - 但在不同的时间尺度下,你知道的魔鬼会更好 :)

谢谢您的帮助。

于 2013-02-08T10:04:44.447 回答