[解決済み] 1000個のEntity Frameworkオブジェクトを作成するとき、いつSaveChanges()を呼び出すべきですか?(インポート中のように)
質問
各実行で 1000 件のレコードを持つインポートを実行しています。 私の仮定についていくつか確認したいことがあります。
これらのうちどれが最も理にかなっていますか。
-
実行する
SaveChanges()
それぞれAddToClassName()
を呼び出します。 -
実行
SaveChanges()
それぞれ n 数AddToClassName()
の呼び出しがあります。 -
実行
SaveChanges()
その後 全て のAddToClassName()
を呼び出します。
最初のオプションは、おそらく遅いですよね? メモリ内の EF オブジェクトを分析し、SQL を生成するなどの作業が必要になるためです。
2番目のオプションは、トライキャッチの周りにラップすることができるので、両方の世界のベストであると仮定します。
SaveChanges()
を呼び出すことができ、失うのは
n
の数のレコードを失うだけです。 各バッチをList<>に格納するとよいでしょう。 もし
SaveChanges()
の呼び出しが成功したら、リストを取り除く。 失敗したら、項目を記録する。
最後のオプションは、おそらく非常に遅くなるでしょう。なぜなら、すべてのEFオブジェクトが
SaveChanges()
が呼び出されるまで、すべてのEFオブジェクトがメモリ上になければならないからです。 そして、保存が失敗した場合、何もコミットされませんよね?
どうすれば解決するのでしょうか?
念のため、まずテストしてみます。パフォーマンスはそれほど悪くはないはずです。
1つのトランザクションですべての行を入力する必要がある場合、AddToClassNameクラスのすべての後にそれを呼び出します。行を独立して入力できる場合は、すべての行の後で変更を保存します。データベースの整合性は重要です。
2番目のオプションは好きではありません。システムにインポートして、1000 行のうち 10 行が拒否され、1 行が悪いという理由だけで拒否されると、(最終ユーザーの観点から)私は混乱するでしょう。10 件のインポートを試してみて、失敗したら、1 件ずつ試して、ログに記録することができます。
時間がかかるかどうかテストしてください。propably」と書かないでください。まだ分かっていないのだから。実際に問題になったときだけ、他の解決策を考える(marc_s)。
EDIT
いくつかのテストをしてみました(時間はミリ秒)。
10000行です。
1行後のSaveChanges():18510,534
100行後のSaveChanges():4350,3075
10000行後のSaveChanges():5233,0635
50000行目
1行後のSaveChanges():78496,929
500行後のSaveChanges():22302,2835
50000行後のSaveChanges():24022,8765
つまり、n行後にコミットする方が、すべて後にコミットするよりも実際には速いのです。
私のお勧めは
- n行後にSaveChanges()を実行します。
- 1つのコミットが失敗したら、それを1つずつ試して、欠陥のある行を見つけます。
クラスをテストします。
TABLEです。
CREATE TABLE [dbo].[TestTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SomeInt] [int] NOT NULL,
[SomeVarchar] [varchar](100) NOT NULL,
[SomeOtherVarchar] [varchar](50) NOT NULL,
[SomeOtherInt] [int] NULL,
CONSTRAINT [PkTestTable] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
クラスです。
public class TestController : Controller
{
//
// GET: /Test/
private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString(int size)
{
var randomSize = _rng.Next(size);
char[] buffer = new char[randomSize];
for (int i = 0; i < randomSize; i++)
{
buffer[i] = _chars[_rng.Next(_chars.Length)];
}
return new string(buffer);
}
public ActionResult EFPerformance()
{
string result = "";
TruncateTable();
result = result + "SaveChanges() after 1 row:" + EFPerformanceTest(10000, 1).TotalMilliseconds + "<br/>";
TruncateTable();
result = result + "SaveChanges() after 100 rows:" + EFPerformanceTest(10000, 100).TotalMilliseconds + "<br/>";
TruncateTable();
result = result + "SaveChanges() after 10000 rows:" + EFPerformanceTest(10000, 10000).TotalMilliseconds + "<br/>";
TruncateTable();
result = result + "SaveChanges() after 1 row:" + EFPerformanceTest(50000, 1).TotalMilliseconds + "<br/>";
TruncateTable();
result = result + "SaveChanges() after 500 rows:" + EFPerformanceTest(50000, 500).TotalMilliseconds + "<br/>";
TruncateTable();
result = result + "SaveChanges() after 50000 rows:" + EFPerformanceTest(50000, 50000).TotalMilliseconds + "<br/>";
TruncateTable();
return Content(result);
}
private void TruncateTable()
{
using (var context = new CamelTrapEntities())
{
var connection = ((EntityConnection)context.Connection).StoreConnection;
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"TRUNCATE TABLE TestTable";
command.ExecuteNonQuery();
}
}
private TimeSpan EFPerformanceTest(int noOfRows, int commitAfterRows)
{
var startDate = DateTime.Now;
using (var context = new CamelTrapEntities())
{
for (int i = 1; i <= noOfRows; ++i)
{
var testItem = new TestTable();
testItem.SomeVarchar = RandomString(100);
testItem.SomeOtherVarchar = RandomString(50);
testItem.SomeInt = _rng.Next(10000);
testItem.SomeOtherInt = _rng.Next(200000);
context.AddToTestTable(testItem);
if (i % commitAfterRows == 0) context.SaveChanges();
}
}
var endDate = DateTime.Now;
return endDate.Subtract(startDate);
}
}
関連
-
[解決済み] 不変量名 'System.Data.SqlClient' を持つ ADO.NET プロバイダに対応する Entity Framework プロバイダが見つかりませんでした。
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] ES6インポートで中括弧を使用するのはどのような場合ですか?
-
[解決済み] コードファーストとモデル・データベースファーストの比較【終了しました
-
[解決済み] Entity Framework: "ストアの更新、挿入、または削除ステートメントが予期しない行数 (0) に影響しました。" [クローズド]。
-
[解決済み】.ToList(), .AsEnumerable(), AsQueryable()の違いは何ですか?
-
[解決済み] Entity Framework Code Firstでオブジェクトをデタッチするにはどうすればいいですか?
-
[解決済み] Entity Framework - やり直し - すべての移行を元に戻す/ロールバックする
-
[解決済み] エンティティフレームワークのコードファーストのNULL外部キー
-
[解決済み] Entity Framework 6のMulti-async?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 不変量名 'System.Data.SqlClient' を持つ ADO.NET プロバイダに対応する Entity Framework プロバイダが見つかりませんでした。
-
[解決済み] Entity Frameworkで生成されたSQLを表示するにはどうすればよいですか?
-
[解決済み] Entity Framework 5で子オブジェクトの子オブジェクトをインクルードする方法
-
[解決済み] EF Code First "Invalid column name 'Discriminator'" but no inheritance.
-
[解決済み] Entity Framework Code First - Fluent ApiとData Annotationsのメリット・デメリット【終了しました
-
[解決済み] Entity Framework 6.2でインデックスを作成する方法とそのコード
-
[解決済み] EF Core の EntityTypeBuilder に ToTable の定義が含まれていない。
-
[解決済み] Entityフレームワークのバルクインサートのパフォーマンス向上【重複あり
-
[解決済み] エンティティフィールドのNullableプロパティ、Entity FrameworkをCode Firstで使う
-
[解決済み] Entity Framework 6のMulti-async?