c# - 简单的 DbSet<TEntity>.Find() 调用永远占用

标签 c# .net entity-framework linq-to-entities

我从 DbSet.Find() 调用中获得糟糕的性能。我的代码如下所示:

public class Area
{
    [Key]
    public string Id { get; protected set; }

    // ...
}

public class MyContext : DbContext
{
    //...
    public DbSet<Area> Areas { get; set; }
    //...
}

// This is the call that takes so long
Area area = context.Areas.Find(id);    

我知道这必须搜索实体集、检查更改跟踪等,并且会触发对数据库的调用。问题是它比简单的 context.Areas.SingleOrDefault(x => x.Id == id) 调用需要更长的数量级。比我认为合理的多得多。根据另一个问题的提示,我也尝试过暂时关闭更改跟踪但没有成功(它似乎没有任何效果):

try
{
    context.Configuration.AutoDetectChangesEnabled = false;
    return context.Areas.Find(id);
}
finally
{
    context.Configuration.AutoDetectChangesEnabled = true;
}

为了弄清真相,我启动了探查器。这是我发现的:

trace

看起来它一直在准备执行计划。但是为什么这会在 .Find() 调用期间花费这么长时间而不是显式 .SingleOrDefault 调用(注意在调用堆栈顶部附近,它实际上是准备一个 SingleOrDefault 调用)。有什么方法可以查看 .Find() 方法实际尝试编译的查询吗?

最佳答案

我从来没有弄清楚为什么要花这么长时间。它生成的查询看起来很合理(只是一个简单的 SELECT)。我正在使用一个非常复杂的域模型,虽然上面描述的 Area 实体是孤立且简单的,但 Entity Framework 可能以某种方式试图构建 View 或生成一个涉及域模型其他部分的查询(或者更确切地说,试图决定它不应该)。

无论如何,我确实制定了一个变通办法。诀窍是手动执行(我认为)Find() 调用首先执行的工作:

public Area FindArea(string id)
{
  // First see if the DbSet already has it in the local cache
  Area area = context.Areas.Local.SingleOrDefault(x => x.Id == id);

  // Then query the database
  return area ?? context.Areas.SingleOrDefault(x => x.Id == id);
}

可以使用扩展方法轻松推广此技术。此特定实现假定实体将其 ID 存储在字符串 Id 列中并实现以下接口(interface)。但是,通过一些调整,您可以使其适应各种领域模型。

public interface IEntityWithId
{
  string Id { get; }
}

public static object FastFind<TEntity>(this DbSet<TEntity> dbSet, string id)
  where TEntity : IEntityWithId, class
{
  // First see if the DbSet already has it in the local cache
  TEntity entity = dbSet.Local.SingleOrDefault(x => x.Id == id);

  // Then query the database
  return entity ?? dbSet.SingleOrDefault(x => x.Id == id);
}      

关于c# - 简单的 DbSet<TEntity>.Find() 调用永远占用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16345114/

相关文章:

c# - 是否可以保证枚举的 ToString 的值是多少?

c# - 更高效的正则表达式或替代方案?

c# - 寻求使用 C# 读取 .yaml 文件的指导

.net - EF Core 中的多对多关系

c# - asp.net MVC 4,标记地点 - 最佳实践(例如酒吧、商店、餐厅)

c# - 无法通过将自己指定为父级来确定相关操作的有效顺序

c# - 命名空间不存在

c# - 如何将我的 Visual Studio 2013 C# .NET MVC 网站发布到 Azure?

c# - 在 C# 的列表中循环遍历列表

java - C++ .NET 相当于 java public static void main()?