Я следую за n-layered шаблоном с уровнем сервиса. Нет уровня хранилища. Учебник - http://techbrij.com/service-layer-entity-framework-asp-net-mvc-unit-testing. Моя проблема здесь в том, что метод GetAll()
здесь абсурдно медленный. Для выполнения простого разбитого на страницы запроса требуется 12 секунд. Это, как представляется, проблема с ЭФ DBSet
, будет получен с помощью метода _context.Set<T>()
Entity Framework DBSet чрезвычайно медленный
Мой EntityService
public class EntityService<T> : IEntityService<T> where T : BaseEntity
{
protected GraphicContext _context;
protected DbSet<T> _dbset;
public EntityService(GraphicContext context)
{
_context = context;
_dbset = _context.Set<T>();
}
public virtual async Task CreateAsync(T entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
_dbset.Add(entity);
await _context.SaveChangesAsync();
}
public virtual async Task<T> FindAsync(params object[] keyValues)
{
if (keyValues == null)
{
throw new ArgumentNullException("id");
}
return await _dbset.FindAsync(keyValues);
}
public virtual async Task UpdateAsync(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
await _context.SaveChangesAsync();
}
public virtual async Task DeleteAsync(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_dbset.Remove(entity);
await _context.SaveChangesAsync();
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
}
Он использует DBSet
, потому что после некоторых исследований IDBSet
является устаревшим и также медленно на нас.
Таблица, к которой мы обращаемся, имеет около 300 000 записей, но мы используем разбиение на страницы, чтобы помочь запросу и для удобства доступа для пользователя. В любом случае, чтобы проверить, что это был вызов _context.Set<T>()
, который был медленным, я пропустил службу и запустил мой контекст в контроллере для выполнения того же запроса. Запрос занял менее секунды.
Кто-нибудь знает, почему это было бы так или есть способ ускорить это? Я думаю, мне, возможно, придется избегать использования метода set(). Любые другие альтернативы этому?
вопрос не является 'DbSet', но' AsEnumerable'. И вообще, 'IEnumerable' тип результата 'GetAll'. Таким образом, вы всегда будете читать всю таблицу в памяти и запускать запросы к памяти с помощью LINQ to Objects. –
Я фактически удалил 'AsEnumerable()' и заменил его просто на 'NoTracking()'. Это ускорило запрос на 3 секунды. По-прежнему потребовалось около 8 или 9 секунд для запуска –
Но вам также нужно изменить тип 'GetAll', в противном случае эффект будет таким же, как с вызовом' AsEnumerable'. например использовать 'IQueryable GetAll' –