Sto seguendo uno schema a più livelli con un livello di servizi. Nessun livello di repository. Il tutorial è http://techbrij.com/service-layer-entity-framework-asp-net-mvc-unit-testing . Il mio problema qui è che il metodo GetAll()
qui è assurdamente lento. Ci vogliono 12 secondi per eseguire una semplice query impaginata. Sembra essere un problema con DBSet
, che viene recuperato utilizzando il _context.Set<T>()
Il mio 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>();
}
}
Sta usando DBSet
perché dopo alcune ricerche IDBSet
è obsoleto ed è stato anche lento con noi.
La tabella a cui stiamo accedendo ha circa 300.000 record, ma stiamo usando la paginazione per aiutare la query e per facilitare l'accesso per l'utente. Ad ogni modo, per verificare che si trattasse della chiamata a _context.Set<T>()
che si sta rallentando, ho saltato il servizio e ho eseguito il mio contesto nel controller per eseguire esattamente la stessa query. La query ha richiesto meno di un secondo.
Qualcuno sa perché questo sarebbe in questo modo o avere un modo per accelerare questo? Sto pensando che potrebbe dover evitare di usare il metodo set (). Qualche altra alternativa a questo?
Quando il tipo di risultato di GetAll
è IEnumerable<T>
, tutte le query sul risultato causeranno il caricamento dell'intera tabella in memoria e quindi l'interrogazione tramite LINQ to Objects.
Se si desidera che le query vengano eseguite nel database (ad esempio tramite LINQ alle entità), rimuovere la chiamata AsEnumerable()
e modificare il tipo GetAll
su IQueryable<T>
:
public virtual IQueryable<T> GetAll()
{
return _dbset;
}