Kle*_*ezk 0 c# linq asp.net-mvc entity-framework-6
我正在使用存储库层.我的问题是,当连接具有大记录的表时,GetAll()方法太慢.运行简单查询需要40秒.
IGenericRepository:
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();
}
Run Code Online (Sandbox Code Playgroud)
GenericRepository:
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
LINQ:
var conceptosDetalle = from pf in _parFactfRepository.GetAll()
join inve in _inveRepository.GetAll() on pf.CVE_ART equals inve.CVE_ART
where inve.STATUS == "A" && pf.CVE_DOC == cveDoc
orderby inve.CTRL_ALM, inve.CVE_ART
select new MyViewModel()
{
CTRL = inve.CTRL_ALM,
CVE_ART = inve.CVE_ART,
UNID = "PIEZA",
CANT = pf.CANT,
DESCR = inve.DESCR,
PREC = pf.PREC,
DESC1 = pf.DESC1,
TOTIMP4 = pf.TOTIMP4
};
Run Code Online (Sandbox Code Playgroud)
该查询返回10条记录.parFactfRepository包含992590行,inveRepository包含41908行.
我做错了什么?
那是因为您正在混合和匹配基于存储库的查询和LINQ查询.您不是进行真正的连接,而是获取每个表的所有行,然后将它们连接到内存中.
解决这个问题的最简单方法可能就是返回IQueryable<TEntity>而不是IEnumerable<TEntity>从GetAll方法中返回.使用IEnumerable<TEntity>强制查询进行评估.如果您要返回,IEnumerable<TEntity>您的数据应该是完全烘焙的,即不需要进一步更改查询(包括连接).
也就是说,这还有一个尝试在EF中使用存储库模式的失败.如果你不是很小心,你最终会引入这样的逻辑错误,这些错误并不明显.实体框架已经实现了存储库模式; 这是一个什么样DbSet的.如果您想要对其进行抽象,请引入服务层.有了它,你只需要一个像这样的方法:
public IEnumerable<MyViewModel> GetConceptosDetalle()
{
...
}
Run Code Online (Sandbox Code Playgroud)
该方法将包含整个查询(直接使用EF,而不是完全不必要的存储库层).这样,您的应用程序只需调用一个返回所需数据的方法,该服务层包含所有逻辑.这是真正的抽象.使用存储库,您的代码库中的逻辑正在流失.
注意:我MyViewModel只是为了便于解释而返回,但实际上,您应该返回某种DTO,然后可以将其映射到您的视图模型.将视图业务逻辑泄漏到服务层是不错的主意.
| 归档时间: |
|
| 查看次数: |
856 次 |
| 最近记录: |