如何提高LINQ到EF的性能

时间:2011-12-18 21:35:31

标签: linq tsql entity-framework

我有两个类:Property和PropertyValue。属性具有多个值,其中每个值都是新修订。

检索一组属性时,我想包含每个属性的最新版本值。

在T-SQL中,这可以非常有效地完成:

SELECT 
p.Id,
pv1.StringValue,
pv1.Revision
FROM dbo.PropertyValues pv1
LEFT JOIN dbo.PropertyValues pv2 ON pv1.Property_Id = pv2.Property_Id AND pv1.Revision < pv2.Revision
JOIN dbo.Properties p ON p.Id = pv1.Property_Id
WHERE pv2.Id IS NULL
ORDER BY p.Id

此查询中的“魔术”是在小于条件的情况下连接并查找没有LEFT JOIN强制结果的行。

如何使用LINQ to EF完成类似的操作?

我能想到的最好的事情是:

from pv in context.PropertyValues
group pv by pv.Property into g
select g.OrderByDescending(p => p.Revision).FirstOrDefault()

它确实产生了正确的结果,但比另一个慢了约10倍。

3 个答案:

答案 0 :(得分:1)

也许这会有所帮助。 db是数据库上下文:

(
            from pv1 in db.PropertyValues
            from pv2 in db.PropertyValues.Where(a=>a.Property_Id==pv1.Property_Id && pv1.Revision<pv2.Revision).DefaultIfEmpty()
            join p in db.Properties
                on pv1.Property_Id equals p.Id
            where pv2.Id==null
            orderby p.Id
            select new
            {
                p.Id,
                pv1.StringValue,
                pv1.Revision
            }
    );

答案 1 :(得分:1)

在Linq To Entities中优化查询之后,您还必须了解Entity Framework将查询转换为SQL然后将结果映射回对象所需的工作。

将Linq To Entities查询直接与SQL查询进行比较将始终导致性能降低,因为实体框架为您做了更多工作。

因此,优化实体框架所采用的步骤也很重要。

可能有所帮助的事情:

  • 预编译您的查询
  • 预生成视图
  • 自行决定何时打开数据库连接
  • 禁用跟踪(如果适用)

Here you can find some documentation有绩效策略。

答案 2 :(得分:0)

如果你想在连接中使用多个条件(小于表达式),你可以这样做

from pv1 in db.PropertyValues
 join pv2 in db.PropertyValues on new{pv1.Property_ID, Condition = pv1.Revision < pv2.Revision} equals new {pv2.Property_ID , Condition = true} into temp
from t in temp.DefaultIfEmpty()
            join p in db.Properties
                on pv1.Property_Id equals p.Id
            where t.Id==null
            orderby p.Id
            select new
            {
                p.Id,
                pv1.StringValue,
                pv1.Revision
            }