Я бы сначала проверил, чтобы быть уверенным. Производительность не должна быть такой уж плохой.
Если вам нужно ввести все строки в одну транзакцию, вызовите ее после всего класса AddToClassName. Если строки можно вводить независимо, сохраняйте изменения после каждой строки. Согласованность базы данных важна.
Второй вариант мне не нравится. Меня бы смутило (с точки зрения конечного пользователя), если бы я сделал импорт в систему, и он отклонил бы 10 строк из 1000 только потому, что 1 — это плохо. Вы можете попробовать импортировать 10, и если это не удастся, попробуйте по одному, а затем зарегистрируйтесь.
Проверьте, если это займет много времени. Не пишите "вероятно". Вы еще этого не знаете. Только когда это действительно проблема, подумайте о другом решении (marc_s).
ИЗМЕНИТЬ
Я сделал несколько тестов (время в миллисекундах):
10 000 строк:
SaveChanges() после 1 строки: 18510 534
SaveChanges() после 100 строк: 4350 3075
SaveChanges() после 10 000 строк: 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
{
//
// 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);
}
}
person
LukLed
schedule
18.12.2009