在对基于Entity Framework 4.0的数据库层进行概要分析后,我发现主要的性能罪人是一个简单的LINQ Any(),用于检查数据库中是否已存在实体。 Any()检查比保存实体的速度慢几个数量级。 数据库中的行数相对较少,正在检查的列已编制索引。
我使用以下LINQ来检查是否存在设置组:
from sg in context.SettingGroups
where sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory)
select sg).Any()
这会生成以下SQL(另外我的SQL分析器声称查询执行了两次):
exec sp_executesql N'SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[SettingGroups] AS [Extent1]
WHERE ([Extent1].[Group] = @p__linq__0) AND ([Extent1].[Category] = @p__linq__1)
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[SettingGroups] AS [Extent2]
WHERE ([Extent2].[Group] = @p__linq__0) AND ([Extent2].[Category] = @p__linq__1)
)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'Cleanup',@p__linq__1=N'Mediator'
现在我只能考虑创建存储过程来解决这个问题,但我当然更愿意将代码保存在LINQ中。
有没有办法让这种“存在”检查更快地用EF运行?
我应该提一下,我也在n层架构中使用自跟踪实体。在某些情况下,某些实体的ChangeTracker状态设置为“已添加”,即使它们已存在于数据库中。这就是为什么我使用检查来相应地更改ChangeTracker状态,如果更新数据库导致插入失败异常。
答案 0 :(得分:1)
尝试通过Group& amp;添加索引到数据库表“SettingGroups”。分类
BTW,这会产生类似的sql吗?var ok = context.SettingGroups.Any(sg => sg.Group==settingGroup && sg.Category==settingCategory);
答案 1 :(得分:0)
我知道这听起来很悲惨,但是如果你使用Count而不是Any会怎么样?
答案 2 :(得分:0)
您是否已经分析了执行生成的select语句的时间与执行select期望/喜欢生成的时间的关系?它可能没有它看起来那么糟糕。
部分
SELECT
1 AS [C1]
FROM [dbo].[SettingGroups] AS [Extent1]
WHERE ([Extent1].[Group] = @p__linq__0) AND ([Extent1].[Category] = @p__linq__1)
可能接近你期望的产量。查询优化器很可能会意识到第二个查询与第一个查询相同,因此它可能会为整个查询添加很少的时间。
答案 3 :(得分:0)
问题是实体框架(至少EF4)正在生成愚蠢的SQL。以下代码似乎可以轻松地生成不错的SQL。
public static class LinqExt
{
public static bool BetterAny<T>( this IQueryable<T> queryable, Expression<Func<T, bool>> predicate)
{
return queryable.Where(predicate).Select(x => (int?)1).FirstOrDefault().HasValue;
}
public static bool BetterAny<T>( this IQueryable<T> queryable)
{
return queryable.Select(x => (int?)1).FirstOrDefault().HasValue;
}
}
然后你可以这样做:
(from sg in context.SettingGroups
where sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory)
select sg).BetterAny()
甚至:
context.SettingGroups.BetterAny(sg => sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory));