2016-04-06 3 views
0

Я следую за 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(). Любые другие альтернативы этому?

+1

вопрос не является 'DbSet', но' AsEnumerable'. И вообще, 'IEnumerable ' тип результата 'GetAll'. Таким образом, вы всегда будете читать всю таблицу в памяти и запускать запросы к памяти с помощью LINQ to Objects. –

+0

Я фактически удалил 'AsEnumerable ()' и заменил его просто на 'NoTracking()'. Это ускорило запрос на 3 секунды. По-прежнему потребовалось около 8 или 9 секунд для запуска –

+2

Но вам также нужно изменить тип 'GetAll', в противном случае эффект будет таким же, как с вызовом' AsEnumerable'. например использовать 'IQueryable GetAll' –

ответ

3

Когда результат результата GetAll равен IEnumerable<T>, все запросы к результату приведут к загрузке всей таблицы в память и последующему запросу через LINQ to Objects.

Если вы хотите, чтобы ваши запросы должны быть выполнены в базе данных (т.е. через LINQ к Entities), удалить AsEnumerable() вызов и изменить GetAll типа в IQueryable<T>:

public virtual IQueryable<T> GetAll() 
{ 
    return _dbset; 
} 
+0

Спасибо за это. –

+0

Добро пожаловать. И извините за последний комментарий, это было ошибочно адресовано вам :) –

Смежные вопросы