从包含6,000条记录的表中获取单个项目大约需要30秒。显然,这是不可接受的,我无法弄清楚为什么。我的堆栈是.NET 4.5,EF 6和Web API 2.我所做的事情有什么明显的错误吗?
// DbSet
internal DbSet<TEntity> _dbSet;
// Ctor
public GenericRepository(TContext context)
{
_context = context;
_context.Configuration.ProxyCreationEnabled = false;
_dbSet = _context.Set<TEntity>();
}
// Really slow method
public TEntity GetByFilter(Func<TEntity,bool> filter, params Expression<Func<TEntity, object>>[] includes)
{
IQueryable<TEntity> query = _dbSet;
if (includes != null)
{
foreach (var include in includes)
query = query.Include(include);
}
var entity = query.Where(filter).FirstOrDefault();
return entity;
}
// Here's how it's called. It returns a single item
var x = _unitOfWork.Repository.GetByFilter(i => i.WinId == id, null);
答案 0 :(得分:8)
这很慢的原因是你在Where
子句中使用linq-to-objects,这意味着你在客户端(C#)而不是服务器(SQL)上执行谓词, C#接收6000个数据库记录,然后在内存中过滤。
您可以看到这一点,因为您的filter
参数属于Func
类型,这意味着您通过IEnumerable.Where扩展程序使用了linq-to-objects。
相反,您要使用的是IQueryable.Where扩展,其中包含Expression
类型的参数。这使用了Entity Framework查询提供程序,因此使用了linq-to-ef。
更新您的方法签名如下:
public TEntity GetByFilter(
Expression<Func<TEntity,bool>> filter,
params Expression<Func<TEntity, object>>[] includes)
下面的stackoverflow回答https://stackoverflow.com/a/793584/507793
进一步说明了这一点