Я бы сначала проверил это, чтобы убедиться. Производительность не должна быть такой уж плохой.
Если вам нужно ввести все строки в одной транзакции, вызовите ее после всего класса AddToClassName. Если строки можно вводить независимо, сохраняйте изменения после каждой строки. Согласованность базы данных важна.
Второй вариант мне не нравится. Меня бы сбило с толку (с точки зрения конечного пользователя), если бы я сделал импорт в систему, и он отклонил бы 10 строк из 1000 только потому, что 1 - это плохо. Вы можете попробовать импортировать 10, и если это не удастся, попробуйте один за другим, а затем войдите.
Протестируйте, если это займет много времени. Не пишите «возможно». Вы еще этого не знаете. Только когда это действительно проблема, подумайте о другом решении (marc_s).
РЕДАКТИРОВАТЬ
Я провел несколько тестов (время в миллисекундах):
10000 рядов:
SaveChanges () после 1 строки: 18510,534
SaveChanges () после 100 строк: 4350,3075
SaveChanges () после 10000 строк: 5233,0635
50000 рядов:
SaveChanges () после 1 строки: 78496 929
SaveChanges () после 500 строк: 22302,2835
SaveChanges () после 50000 строк: 24022,8765
Так что на самом деле совершить фиксацию после n строк быстрее, чем после всего.
Моя рекомендация:
- SaveChanges () после n строк.
- Если одна фиксация не удалась, попробуйте ее одну за другой, чтобы найти неисправную строку.
Тестовые классы:
СТОЛ:
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);
}
}