2016-04-06 45 views
0

サービスレイヤーを使用してnレイヤーのパターンを実行しています。リポジトリレイヤはありません。チュートリアルはhttp://techbrij.com/service-layer-entity-framework-asp-net-mvc-unit-testingです。ここでの私の問題は、GetAll()の方法はここではばかげて遅いです。単純なページ付けクエリを実行するのに12秒かかります。いくつかの研究IDBSet後に廃止されており、また、私たちに遅かったので、それは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>(); 
    } 
} 

を使用して取得されたEF DBSetの問題、のようです。

アクセスしているテーブルには約300,000レコードがありますが、ページングを使用してクエリを支援し、ユーザーのアクセスを容易にしています。とにかく、それは遅いです_context.Set<T>()への呼び出しだったことをテストするために、私はサービスをスキップし、全く同じクエリを実行するためにコントローラで私のコンテキストを走らせました。クエリは1秒未満で完了しました。

これがこの方法になる理由を知っている人や、これをスピードアップする方法を知っている人はいますか?私はset()メソッドの使用を避けなければならないかもしれないと思っています。これに対する他の選択肢はありますか?

+1

問題が '' DbSet'ではありませんが、 AsEnumerable'。一般的に 'Getnll'の結果の' IEnumerable 'タイプです。このようにして、常にメモリ内のテーブル全体を読み取り、LINQ to Objectを使用してメモリに対してクエリを実行します。 –

+0

私は実際には 'AsEnumerable ()'を削除し、単純に 'NoTracking()'に置き換えました。それは3秒でクエリをスピードアップしました。実行には約8〜9秒かかりました。 –

+2

でも 'GetAll'型を変更する必要があります。それ以外の場合は、' AsEnumerable'呼び出しと同じ効果があります。例えば'IQueryable GetAll'を使用してください。 –

答えて

3

GetAllの結果の種類がIEnumerable<T>の場合、結果に対するすべてのクエリは、テーブル全体をメモリに読み込み、LINQ to Objectsを介してクエリを実行します。

あなたのクエリが(エンティティへのLINQを経由してすなわち)データベースで実行させたい場合は、AsEnumerable()呼び出しを削除し、IQueryable<T>GetAll種類を変更:

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

ありがとうございました。 –

+0

ようこそ。最後のコメントを申し訳ありません、それは間違ってあなたに対処されました:) –

関連する問題