Asp.net mvc 实体框架5代码优先中的许多重复查询(n+;1)

Asp.net mvc 实体框架5代码优先中的许多重复查询(n+;1),asp.net-mvc,performance,ef-code-first,entity-framework-5,Asp.net Mvc,Performance,Ef Code First,Entity Framework 5,我们的一个承包商使用代码优先的方法实现了一个存储库模式。我们使用服务定位器作为DI模式。当我们从数据库中检索数据时,我们将接口传递给GetQueryable函数并获取数据。但是,我发现我们的应用程序存在严重的性能问题。我实现了MiniProfiler和MiniProfiler.EF来查看瓶颈在哪里 我们有一个case表,它有很多字段(大约25个),其中一些字段以一对一和一对多的形式与其他表关联(只有一个字段与其他表有很多关系)。当我尝试查看案例详细信息时,它会运行大约400个SQL查询,就min

我们的一个承包商使用代码优先的方法实现了一个存储库模式。我们使用服务定位器作为DI模式。当我们从数据库中检索数据时,我们将接口传递给GetQueryable函数并获取数据。但是,我发现我们的应用程序存在严重的性能问题。我实现了MiniProfiler和MiniProfiler.EF来查看瓶颈在哪里

我们有一个case表,它有很多字段(大约25个),其中一些字段以一对一和一对多的形式与其他表关联(只有一个字段与其他表有很多关系)。当我尝试查看案例详细信息时,它会运行大约400个SQL查询,就miniprofiler而言,SQL占用了大约40%的加载时间。这里是我们的GetQueryable和Find方法

      public IQueryable<T> GetQueryable<T>(params string[] includes)
    {
        Type type = _impls.Value[typeof (T).Name].GetType();
        DbSet dbSet = Db.Set(type);
        foreach (var include in includes)
        {
            dbSet.Include(include);
        }
        return ((IQueryable<T>) dbSet);
    }
public IQueryable GetQueryable(参数字符串[]包括)
{
Type Type=_impls.Value[typeof(T).Name].GetType();
DbSet DbSet=Db.Set(类型);
foreach(包含在包含中的var)
{
dbSet.Include(包括);
}
返回((IQueryable)dbSet);
}
我在这个方法中添加了include以附加其他相关的表,但这并没有任何区别。这里是Find方法

  public T Find<T>(long? id)
    {
        Type type = _impls.Value[typeof(T).Name].GetType();
        return (T) Db.Set(type).Find(id);
    }
public找不到(长?id)
{
Type Type=_impls.Value[typeof(T).Name].GetType();
返回(T)Db.Set(type).Find(id);
}
我几乎尝试应用所有性能改进,但SQL查询的数量并没有减少。我试图禁用延迟加载,但它在应用程序的其他部分造成了许多问题

只是一些额外的信息,在case表中有70000行,而in-out对话框表中有500000行。案例和对话是一对多的关联。每个案例都有20-40个对话框条目

我的问题是,

  • 为什么我使用时包含没有任何区别
  • 是否有其他方法可以裁剪运行的查询数
  • 你认为执行是个问题吗

谢谢

Include
返回一个新的
IQueryable
,并且不修改源查询。此外,您还可以使用
Set
的通用版本,这将代码简化了一点:

public IQueryable<T> GetQueryable<T>(params string[] includes)
{
    IQueryable<T> query = Db.Set<T>();
    foreach (var include in includes)
    {
        query = query.Include(include);
    }
    return query;
}
public IQueryable GetQueryable(参数字符串[]包括)
{
IQueryable query=Db.Set();
foreach(包含在包含中的var)
{
query=query.Include(包含);
}
返回查询;
}

Include
返回一个新的
IQueryable
,并且不修改源查询。此外,您还可以使用
Set
的通用版本,这将代码简化了一点:

public IQueryable<T> GetQueryable<T>(params string[] includes)
{
    IQueryable<T> query = Db.Set<T>();
    foreach (var include in includes)
    {
        query = query.Include(include);
    }
    return query;
}
public IQueryable GetQueryable(参数字符串[]包括)
{
IQueryable query=Db.Set();
foreach(包含在包含中的var)
{
query=query.Include(包含);
}
返回查询;
}

Include
返回一个新的
IQueryable
,并且不修改源查询。此外,您还可以使用
Set
的通用版本,这将代码简化了一点:

public IQueryable<T> GetQueryable<T>(params string[] includes)
{
    IQueryable<T> query = Db.Set<T>();
    foreach (var include in includes)
    {
        query = query.Include(include);
    }
    return query;
}
public IQueryable GetQueryable(参数字符串[]包括)
{
IQueryable query=Db.Set();
foreach(包含在包含中的var)
{
query=query.Include(包含);
}
返回查询;
}

Include
返回一个新的
IQueryable
,并且不修改源查询。此外,您还可以使用
Set
的通用版本,这将代码简化了一点:

public IQueryable<T> GetQueryable<T>(params string[] includes)
{
    IQueryable<T> query = Db.Set<T>();
    foreach (var include in includes)
    {
        query = query.Include(include);
    }
    return query;
}
public IQueryable GetQueryable(参数字符串[]包括)
{
IQueryable query=Db.Set();
foreach(包含在包含中的var)
{
query=query.Include(包含);
}
返回查询;
}

第1步:解雇承包商。认真地比如现在。这是一些糟糕的代码。他们不仅错过了使用通用版本的
Set
这样简单而基本的东西,而且他们成功地使使用实体框架变得更加复杂,因为存储库所做的只是使用具有自己独特且非标准化API的代理实体框架方法

也就是说,这里真的没有足够的信息来诊断您的问题是什么。使用
Include
可能会产生更大的查询,但实际上应该可以减少发出的查询总数。这是可能的,你只是没有在你应该在的地方使用includes


现在,您“试图禁用延迟加载,但它在应用程序的其他部分造成了许多问题”,这意味着您过于依赖延迟加载。基本上,你正在加载你甚至不知道的东西,这是优化的对立面。具有讽刺意味的是,实际上最好的方法是继续并禁用延迟加载,然后跟踪代码因延迟加载而失败的地方。如果您想实际延迟加载该东西,可以使用
.load
(请参阅:)。但是,如果您想减少查询,那么您知道需要添加哪些内容。

步骤1:解雇您的承包商。认真地比如现在。这是一些糟糕的代码。他们不仅错过了使用通用版本的
Set
这样简单而基本的东西,而且他们成功地使使用实体框架变得更加复杂,因为存储库所做的只是使用具有自己独特且非标准化API的代理实体框架方法

也就是说,这里真的没有足够的信息来诊断您的问题是什么。使用
Include
可能会产生更大的查询,但实际上应该可以减少发出的查询总数。这是可能的,你只是没有在你应该在的地方使用includes

现在,您“试图禁用延迟加载,但它在应用程序的其他部分造成了许多问题”,这意味着您过于依赖延迟加载。基本上,你是在装你想要的东西