確かに最初にテストします。パフォーマンスはそれほど悪くなくてもかまいません。
1つのトランザクションにすべての行を入力する必要がある場合は、AddToClassNameクラスのすべての後に呼び出します。行を個別に入力できる場合は、行ごとに変更を保存します。データベースの一貫性は重要です。
私が好きではない2番目のオプション。システムにインポートした場合、(最終ユーザーの観点から)混乱し、1が悪いという理由だけで、1000行のうち10行が減少します。10をインポートして失敗した場合は、1つずつ試してからログに記録してください。
時間がかかるかどうかをテストします。「適切に」と書かないでください。あなたはまだそれを知りません。それが実際に問題である場合にのみ、他の解決策(marc_s)について考えてください。
編集
私はいくつかのテストを行いました(ミリ秒単位の時間):
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つずつ試して、障害のある行を見つけてください。
テストクラス:
テーブル:
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
{
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);
}
}