C# 实体框架repostory模式GetAll()太慢
我正在使用存储库层。这里我的问题是GetAll()方法在连接具有大记录的表时太慢。运行一个简单的查询需要40秒 IGenericRepository:C# 实体框架repostory模式GetAll()太慢,c#,asp.net-mvc,linq,entity-framework-6,C#,Asp.net Mvc,Linq,Entity Framework 6,我正在使用存储库层。这里我的问题是GetAll()方法在连接具有大记录的表时太慢。运行一个简单的查询需要40秒 IGenericRepository: public interface IGenericRepository<TEntity> { TEntity FindBy(Expression<Func<TEntity, bool>> predicate); IEnumerable<TEntity> GetAll(); T
public interface IGenericRepository<TEntity>
{
TEntity FindBy(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetAll();
TEntity GetById(int id);
TEntity Insert(TEntity entity);
TEntity Update(TEntity entity);
void Delete(object id);
void Save();
}
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private MyStoreContext _dbContext;
protected DbSet<TEntity> DbSet;
public GenericRepository()
{
_dbContext = new MyStoreContext ();
DbSet = _dbContext.Set<TEntity>();
}
public TEntity FindBy(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).SingleOrDefault();
}
public IEnumerable<TEntity> GetAll()
{
return DbSet.AsNoTracking();
}
public TEntity GetById(int id)
{
return DbSet.Find(id);
}
public TEntity Insert(TEntity entity)
{
DbSet.Add(entity);
Save();
return entity;
}
public TEntity Update(TEntity obj)
{
DbSet.Attach(obj);
_dbContext.Entry(obj).State = EntityState.Modified;
Save();
return obj;
}
public void Delete(object id)
{
TEntity entityToDelete = DbSet.Find(id);
Delete(entityToDelete);
}
public void Delete(TEntity entityToDelete)
{
if (_dbContext.Entry(entityToDelete).State == EntityState.Detached)
{
DbSet.Attach(entityToDelete);
}
DbSet.Remove(entityToDelete);
Save();
}
public void Save()
{
try
{
_dbContext.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
System.Console.WriteLine("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); // you just put the log to know the errors
}
}
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_dbContext != null)
{
_dbContext.Dispose();
_dbContext = null;
}
}
}
}
查询返回10条记录。ParfactFreposition包含992590行,Invereposition包含41908行
我做错了什么?这是因为您混合和匹配了基于存储库的查询和LINQ查询。与其进行真正的联接,不如获取每个表的所有行,然后在内存中联接它们 解决此问题的最简单方法可能是从
GetAll
方法返回IQueryable
,而不是IEnumerable
。使用IEnumerable
强制查询求值。如果要返回IEnumerable
,则应完全烘焙数据,即不需要对查询进行进一步修改(包括联接)
也就是说,这是尝试将存储库模式与EF一起使用的又一个失败。如果你不十分小心,你最终会引入这样的逻辑错误,这些错误的发生原因并不明显。实体框架已经实现了存储库模式;这就是DbSet
的含义。如果您想在上面进行抽象,请引入服务层。这样,您就可以简单地使用如下方法:
public IEnumerable<MyViewModel> GetConceptosDetalle()
{
...
}
public IEnumerable GetConceptosDetalle()
{
...
}
该方法将包含整个查询(直接使用EF,而不是完全不必要的存储库层)。这样,应用程序只需调用一个返回所需数据的方法,服务层包含所有逻辑。这才是真正的抽象。有了存储库,您的代码库中就到处都是逻辑
注意:为了便于解释,我让它返回
MyViewModel
,但实际上,您应该返回某种DTO,然后可以将其映射到视图模型。将视图业务逻辑泄漏到服务层是个坏主意。我认为这将下载这两个表的全部内容,并将它们连接到内存中,而不是数据库中,因为GetAll
是IEnumerable
。非常感谢您的建议。现在我正在努力+1反对将实体框架包装在存储库/工作单元模式中的做法非常困难,因为这是一个小问题。本周到目前为止,我已经两次努力地进行这场对话。@BradleyUffner:我不需要投票。没有充分的理由将存储库模式与EF或任何ORM周期一起使用。存储库模式解决的问题是由ORM解决的,这就是为什么我所见过的几乎所有ORM都实现了存储库模式。如果你的目标是抽象EF,那么还有更合适的方法,比如前面提到的服务层。对,我只是想表达我对这一点的同意,因为我觉得我需要每周向工作中的人们解释同样的事情。@Rolando:好吧,不是自我推销,但有一点:和。我不知道其他人写的任何东西,但我相信一个简单的谷歌搜索可以浮出水面。
public IEnumerable<MyViewModel> GetConceptosDetalle()
{
...
}