简体   繁体   English

实体框架流利的按表类型性能替代

[英]Entity Framework Fluent, Table-Per-Type performance alternatives

I'm currently working on a EF Fluent project (yes, I do like writing it like that) that is taking a model first approach with Table-Per-Type architecture on EF 4.3. 我目前正在研究EF Fluent项目(是的,我确实喜欢这样写),该项目采用EF 4.3上的Table-Per-Type体系结构采用模型优先的方法。

As I've found out over the past couple of months, Table-Per-Type and inheritance just doesn't play nice -> more information . 正如我在过去几个月中发现的那样,Table-Per-Type和继承只是不能很好地发挥作用-> 更多信息 I'm using a single base class with seven derived classes and just returning items across the seven derived classes isn't particular fast. 我使用的是带有七个派生类的单个基类,而返回七个派生类中的项目并不是特别快。 In terms of execution timings, to retreive a list of five records EF is taking a between 5 to 7 seconds, subsequent executions are around the 2.5 to 4 second mark. 在执行时间方面,要检索5条记录的清单EF花费5到7秒之间的时间,后续执行大约需要2.5到4秒的标记。 Safe to say this is just unacceptable so I'm looking at alternative methods... 可以肯定地说这是不可接受的,所以我正在寻找替代方法...

What I can do is hit the database multiple times, ie attempt to retreive each type of object individual and collate into a single collection; 我所能做的就是多次访问数据库,即尝试检索每种类型的单个对象并整理为一个集合; however, the code is unwieldly at best, ie 但是,代码充其量是多余的,即

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;

But it works! 但这有效! The first hit on the database takes 2 seconds and subsequent queries a mere 200 milliseconds. 第一次命中数据库需要2秒钟,随后的查询仅需200毫秒。

My problem is that this is not very elegant, maintainable, etc, etc. I have been toying with casting the dbContext into an ObjectContext and running with something like this with a stored procedure ('spGetMyDerivedItems') returning all of the derived resultsets ordered in one db hit... 我的问题是,这不是很优雅,不可维护,等等。我一直在玩弄将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;

However, this doesn't work with a InvalidOperationException complaining that the CommandText is not valid and that I must provide a 'ContainerName'. 但是,这不适用于InvalidOperationException,因为它抱怨CommandText无效,并且我必须提供'ContainerName'。 My guessing here is that if I was using an EDMX file, I could set this set item (and using the DefaultContainerName doesn't work). 我的猜测是,如果我使用的是EDMX文件,则可以设置此设置项(并且使用DefaultContainerName不起作用)。 But I'm taking a fluent approach and I feel I've hit a dead end. 但是我使用的是流利的方法,我觉得自己已经走到了尽头。

So... 所以...

What approaches are available to resolving the performance problems of EF and table-per-type? 有哪些方法可以解决EF和每类型表的性能问题? Is it possible to execute a stored procedure through the ObjectContext with Fluent / Model First approach? 是否可以使用Fluent / Model First方法通过ObjectContext执行存储过程? Can I execute a standard SQLClient.SqlDataReader and translate into an ObjectContext? 我可以执行标准的SQLClient.SqlDataReader并将其转换为ObjectContext吗?

Thanks in advance... 提前致谢...

OK - it appears that the ObjectContext can translate from System.Data.SqlClient.SqlDataReader meaning I don't need to derive (directly) from the dbContext. OK-看来ObjectContext可以从System.Data.SqlClient.SqlDataReader转换,这意味着我不需要(直接)从dbContext派生。 Here's the example code... 这是示例代码...

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;

Obviously the best answer is that EF would pick this up but I'm happy with the above for the moment. 显然,最好的答案是EF会采取这一措施,但我暂时对以上情况感到满意。 Moving to EF5 sounds like a good move - but with various timescales its better the devil you know :) 迁移到EF5听起来是个不错的选择-但在各种时间范围内,您所知道的魔鬼更好:)

Thanks for the help. 谢谢您的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM