Я б спершу протестував це, щоб бути впевненим. Продуктивність не повинна бути такою поганою.
Якщо вам потрібно ввести всі рядки в одній транзакції, викликайте це після всього класу AddToClassName. Якщо рядки можна вводити самостійно, збережіть зміни після кожного рядка. Послідовність бази даних є важливою.
Другий варіант мені не подобається. Для мене було б заплутано (з точки зору кінцевого користувача), якби я здійснив імпорт до системи, і вона зменшила б 10 рядків з 1000, просто тому, що 1 поганий. Ви можете спробувати імпортувати 10, і якщо це не вдається, спробуйте по черзі, а потім увійдіть.
Перевірте, чи це займає багато часу. Не пишіть `` з поширенням ''. Ви ще цього не знаєте. Тільки тоді, коли це насправді проблема, подумайте про інше рішення (marc_s).
РЕДАГУВАТИ
Я провів кілька тестів (час у мілісекундах):
10000 рядків:
SaveChanges () після 1 рядка: 18510,534 SaveChanges
() після 100 рядків: 4350,3075 SaveChanges
() після 10000 рядків: 5233,0635
50000 рядків:
SaveChanges () після 1 рядка: 78496929 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);
}
}