[解決済み] Entity Framework SaveChanges() と SaveChangesAsync() の比較と Find() と FindAsync() の比較
質問
上記の2つのペアの違いについて調べているのですが、明確に説明している記事がなく、また、どのような場合にどちらを使用するのかがわかりません。
では
SaveChanges()
と
SaveChangesAsync()
?
そして、その間に
Find()
と
FindAsync()
?
サーバ側では
Async
メソッドを使用する場合にも
await
. 従って、サーバー側では非同期ではないと思います。
クライアント側のブラウザでUIブロックを防ぐのに役立つだけなのでしょうか?あるいは、両者の間に長所と短所があるのでしょうか?
どのように解決するのですか?
リモートサーバー上でアクションを実行する必要があるときはいつでも、あなたのプログラムはリクエストを生成し、それを送信し、そして応答を待ちます。ここでは
SaveChanges()
と
SaveChangesAsync()
を例として挙げましたが、同じように
Find()
と
FindAsync()
.
例えば、リスト
myList
というリストがあり、それをデータベースに追加する必要があるとします。それを挿入するために、あなたの関数は次のようなものになるでしょう。
using(var context = new MyEDM())
{
context.MyTable.AddRange(myList);
context.SaveChanges();
}
まず
MyEDM
を作成し、リスト
myList
をテーブル
MyTable
を呼び出した後
SaveChanges()
を呼び出して変更をデータベースに永続化します。レコードはコミットされますが、プログラムはコミットが終了するまで他のことは何もできません。これは、コミットする内容によっては長い時間がかかることがあります。レコードへの変更をコミットする場合、エンティティはそれらを一度にコミットする必要があります (私はかつて、保存が更新のために 2 分かかったことがあります)!
この問題を解決するには、2 つの方法のうちの 1 つを実行します。1 つ目は、挿入を処理するために新しいスレッドを立ち上げることです。これは、実行を続けるために呼び出し側のスレッドを解放しますが、ただそこに座って待つだけの新しいスレッドを作成したことになります。そのようなオーバーヘッドは必要ありません。
async await
パターンが解決してくれます。
I/Oの対向のために
await
はすぐにあなたの親友になります。上記のコードセクションを利用して、次のように修正することができます。
using(var context = new MyEDM())
{
Console.WriteLine("Save Starting");
context.MyTable.AddRange(myList);
await context.SaveChangesAsync();
Console.WriteLine("Save Complete");
}
とても小さな変更ですが、コードの効率とパフォーマンスに大きな効果があります。では、どうなるのでしょうか?コードの始まりは同じです。
MyEDM
のインスタンスを作成し、そこに
myList
に
MyTable
. しかし
await context.SaveChangesAsync()
を呼び出すと、コードの実行は
は呼び出し元の関数に戻ります!
つまり、すべてのレコードがコミットされるのを待っている間、あなたのコードは実行を続けることができるのです。上記のコードを含む関数が次のようなシグネチャを持っていたとします。
public async Task SaveRecords(List<MyTable> saveList)
というシグネチャを持っていたとすると、呼び出し側の関数は次のようになります。
public async Task MyCallingFunction()
{
Console.WriteLine("Function Starting");
Task saveTask = SaveRecords(GenerateNewRecords());
for(int i = 0; i < 1000; i++){
Console.WriteLine("Continuing to execute!");
}
await saveTask;
Console.Log("Function Complete");
}
なぜこのような関数があるのか、私にはわかりませんが、この関数が出力するものは、どのように
async await
がどのように機能するかを示しています。まず、何が起こるかを確認しましょう。
実行が入る
MyCallingFunction
,
Function Starting
では
Save Starting
がコンソールに書き込まれ、その後、関数
SaveChangesAsync()
が呼び出される。この時点で、実行は
MyCallingFunction
に戻り、「実行の継続」を1000回まで書き続けるforループに入る。このとき
SaveChangesAsync()
が終了すると、実行は
SaveRecords
関数に戻り
Save Complete
をコンソールに書き出します。一度、すべての
SaveRecords
が完了すると、実行は
MyCallingFunction
で実行を継続します。
SaveChangesAsync()
が終了しました。混乱しましたか?以下は出力例です。
関数開始 保存 開始 実行継続中 実行継続 実行継続 実行の継続! 実行中! .... 実行の継続! 保存完了! 実行の続き! 実行の続き! 実行継続中 .... 実行継続中! 機能完了
あるいは、そうかもしれません。
起動時の機能 起動を保存 実行継続中 実行継続 保存完了 実行継続! 実行中 実行の続き! .... 実行継続中! 機能完了
の素晴らしさです。
async await
とすることで、何かの終了を待っている間、コードを実行し続けることができます。実際には、このような関数を呼び出し関数として持つことになります。
public async Task MyCallingFunction()
{
List<Task> myTasks = new List<Task>();
myTasks.Add(SaveRecords(GenerateNewRecords()));
myTasks.Add(SaveRecords2(GenerateNewRecords2()));
myTasks.Add(SaveRecords3(GenerateNewRecords3()));
myTasks.Add(SaveRecords4(GenerateNewRecords4()));
await Task.WhenAll(myTasks.ToArray());
}
ここでは、4種類の保存記録関数があります。
が同時に
.
MyCallingFunction
を使うと、より速く完了します。
async await
を使うと、個々の
SaveRecords
関数が直列に呼ばれる場合よりも
まだ触れていないのが、この
await
キーワードです。これは現在の関数の実行を停止させるものです。
Task
が完了するまで現在の関数を停止させます。つまり、オリジナルの
MyCallingFunction
という行は
Function Complete
の行がコンソールに書き込まれるのは
SaveRecords
関数が終了するまでコンソールには書き込まれません。
長い話になりますが、もしオプションで
async await
を使用するオプションがある場合は、アプリケーションのパフォーマンスを大幅に向上させることができるため、使用する必要があります。
関連
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】"指定されたパスのフォーマットはサポートされていません。"
-
[解決済み] 不変量名 'System.Data.SqlClient' を持つ ADO.NET プロバイダに対応する Entity Framework プロバイダが見つかりませんでした。
-
[解決済み] Entity Framework 5 レコードを更新する
-
[解決済み] Entity FrameworkとLINQ to SQLの比較
-
[解決済み] Entity Frameworkにおける最速の挿入方法
-
[解決済み] Entity Frameworkで生成されたSQLを表示するにはどうすればよいですか?
-
[解決済み] すべてのサーバーサイドのコードでConfigureAwaitを呼び出すためのベストプラクティス
-
[解決済み] Entity Framework - 複数レベルのプロパティを含める
-
[解決済み】非同期プログラミングとマルチスレッドの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】プロジェクトビルド時のエラー。エディタでスクリプトにコンパイルエラーがあるため、Playerのビルドにエラーが発生する
-
[解決済み】ORA-01008: すべての変数がバインドされていません。これらはバインドされています。
-
[解決済み】WPFでXamlファイルにコメントを追加する方法は?
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み] EntityTypeにキーが定義されていないエラー
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】ユーザー設定値を別のユーザー設定値で設定する