我希望我能得到一些帮助来解决我在 EntityFramework 4.4 中遇到的性能问题。我正在将一个使用 EDMX 文件的应用程序首先转换为代码,并且在 LINQ 查询的“where”子句中运行具有大量对象的查询时遇到了问题。
以下是对所有内容的布局方式的简要概述(实体不是指 EF,它是我们代码中为通用“事物”提供的名称):
public class ExampleDbContext : DbContext
{
public DbSet<EntityTag> EntityTags { get; set; }
public DbSet<Entity> Entities { get; set; }
public DbSet<Log> Logs { get; set; }
protected override void OnModelCreating(DbmodelBuilder modelBuilder)
{
// Fluent mappings added to modelBuilder.Configurations.Add() in here
}
}
public class EntityTag
{
public int Id { get; set; }
public virtual Entity Entity { get; set; }
public int EntityId { get; set; }
public virtual Log Deleted { get; set; }
public int? DeletedId { get; set; }
}
public class Entity
{
public int Id { get; set; }
pulic byte[] CompositeId { get; set; }
}
// Used to log when an event happens
public class Log
{
public int Id { get; set; }
public string Username { get; set; }
public DateTime Timestamp { get; set; }
}
我正在运行的导致问题的查询是:
// Creates an IEnumerable<byte[]> with the keys to find
var computedKeys = CreateCompositeIDs(entityKeys);
// Run the query and find any EntityTag that isn't deleted and is in
// the computedKeys list
var result = from et in Context.EntityTags
where computedKeys.Contains(et.Entity.CompositeId) &&
et.Deleted == null
select et;
var entityTags = result.ToList();
当 computedKeys 仅包含几个 Id(例如 15 个)时,代码和查询会快速运行。当我有大量 Id(此时 1600 是正常的,并且可能会变得更高)时,一旦使用ToList()
. 我还computedKeys.Contains()
从查询中删除了大量的(离开 et.Deleted),computedKeys
并且查询最终快速运行。
通过调试,我确定创建键列表很快,所以这不是问题。当我将探查器连接到 MSSQL 以查看生成的查询时,它看起来很正常,因为所有 CompositeId 都包含在 a 中WHERE CompositeId IN ( /* List of Ids, could be 1500 of them */)
,并且当查询显示在探查器中时,它会在不到一秒的时间内执行,所以我不认为它是数据库优化的事情,要么。分析器将坐在那里,在它运行的整个过程中,从最后一秒左右开始,当它快速返回结果时,它不会出现任何东西。
我连接了 dotTrace,看起来很多时间都花在System.Data.Query.PlanCompiler.JoinGraph.GenerateTransitiveEdge(JoinEdge, JoinEdge)
(119,640 毫秒)System.Collections.Generic.List+Enumerator
内,我认为,根据每个方法的总执行时间,在该方法中调用了 1.MoveNext`(54,270 毫秒)两次。
我似乎无法弄清楚为什么生成查询需要这么长时间。编译后第二次执行似乎也没有更快,所以它看起来不像被缓存。
在此先感谢您的帮助!