タイトルが示すように、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
最初のクエリで、EFはモデルをコンパイルします。これほど大きなモデルの場合、これにはかなりの時間がかかります。
3つの提案を次に示します。 http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/
まとめ:
また、ベンチマークを実行するときに、リリースモードでアプリケーションをコンパイルするようにします。
別の解決策は、DBContextの分割を見ることです。 400個のエンティティが非常に多く、小さなチャンクで作業する方が適切です。試したことはありませんが、1つずつロードするのに15秒かかることはないので、モデルを1つずつ作成できると思います。 Julie Lermanによるこの投稿を参照してください https://msdn.Microsoft.com/en-us/magazine/jj883952.aspx
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を起動して忘れてもかまいません。
このようなものを試すことができます:(それは私のために働いた)
protected void Application_Start()
{
Start(() =>
{
using (EF.DMEntities context = new EF.DMEntities())
{
context.DMUsers.FirstOrDefault();
}
});
}
private void Start(Action a)
{
a.BeginInvoke(null, null);
}
私のためのこの仕事:
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();
}
C#で使用されていないテーブルが多数ある場合は、それらを除外します。
部分クラスを追加し、次のコードを追加して、OnModelCreatingでこの関数を参照します
void ExcludedTables(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<Table1>();
modelBuilder.Ignore<Table>();
// And so on
}