web-dev-qa-db-ja.com

エンティティフレームワークは、すべてのコンパイル後に初めてロードするのが非常に遅い

タイトルが示すように、Entity Frameworkを使用したSQL Serverデータベースに対する最初のクエリで問題が発生しています。私は答えを探してみましたが、これに対する解決策を実際に持っている人はいないようです。

テストはEntity Framework 6を​​使用してVisual Studio 2012で行われました。また、T4ビューテンプレートを使用してビューをプリコンパイルしました。データベースはSQL Server 2008上にありました。約400のPOCO(400のマッピングファイル)があり、データベーステーブルには100行のデータしかありません。

次のキャプチャは、テストコードと結果です。

static void Main(string[] args){
    Stopwatch st=new Stopwatch();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("First Time "+st.ElapsedMilliseconds+ " milliseconds");

    st.Reset();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("Second Time "+st.ElapsedMilliseconds+ " milliseconds");
}

試験結果

First Time 15480 milliseconds
Second Time 10 milliseconds
42
LeoLi

最初のクエリで、EFはモデルをコンパイルします。これほど大きなモデルの場合、これにはかなりの時間がかかります。

3つの提案を次に示します。 http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/

まとめ:

  1. キャッシュされたdbモデルストアの使用
  2. プリコンパイルされたビューを生成する
  3. N-genを使用してエンティティフレームワークのプリコンパイルバージョンを生成し、ジッターを回避します

また、ベンチマークを実行するときに、リリースモードでアプリケーションをコンパイルするようにします。

別の解決策は、DBContextの分割を見ることです。 400個のエンティティが非常に多く、小さなチャンクで作業する方が適切です。試したことはありませんが、1つずつロードするのに15秒かかることはないので、モデルを1つずつ作成できると思います。 Julie Lermanによるこの投稿を参照してください https://msdn.Microsoft.com/en-us/magazine/jj883952.aspx

38
Mikael Eliasson

EF Coreを使用すると、services.AddDbContext(おそらくEF6でも同様のことができますが、テストしていません)。

services.AddDbContext<MyDbContext>(options => ...);
var options = services.BuildServiceProvider()
                      .GetRequiredService<DbContextOptions<MyDbContext>>();
Task.Run(() =>
{
    using(var dbContext = new MyDbContext(options))
    {
        var model = dbContext.Model; //force the model creation
    }
});

これにより、別のスレッドでdbcontextのモデルが作成され、アプリケーションの残りの初期化(および他のウォームアップ)が行われ、リクエストが開始されます。これにより、すぐに準備が整います。必要な場合、EFCoreはモデルが作成されていない場合は作成されるのを待ちます。 ModelはすべてのDbContextインスタンスで共有されるため、このダミーdbcontextを起動して忘れてもかまいません。

3
Yepeekai

このようなものを試すことができます:(それは私のために働いた)

protected void Application_Start()
{

    Start(() =>
    {
        using (EF.DMEntities context = new EF.DMEntities())
        {
            context.DMUsers.FirstOrDefault();
        }
    });
}
private void Start(Action a)
{
    a.BeginInvoke(null, null);
} 

Entity Framework-最初のクエリが遅い

3
AllmanTool

私のためのこの仕事:

using (MyEntities db = new MyEntities())                
{
   db.Configuration.AutoDetectChangesEnabled = false; // <----- trick
   db.Configuration.LazyLoadingEnabled = false; // <----- trick

   DateTime Created = DateTime.Now;

   var obj = from tbl in db.MyTable
      where DateTime.Compare(tbl.Created, Created) == 0
      select tbl;

   dataGrid1.ItemsSource = obj.ToList();
   dataGrid.Items.Refresh();
}
1
user3047352

C#で使用されていないテーブルが多数ある場合は、それらを除外します。

部分クラスを追加し、次のコードを追加して、OnModelCreatingでこの関数を参照します

void ExcludedTables(DbModelBuilder modelBuilder)
{
    modelBuilder.Ignore<Table1>();
    modelBuilder.Ignore<Table>();
   // And so on
}
0
roncansan