Najpierw przetestowałbym to, aby mieć pewność. Wydajność nie musi być taka zła.
Jeśli chcesz wprowadzić wszystkie wiersze w jednej transakcji, wywołaj ją po całej klasie AddToClassName. Jeśli wiersze można wprowadzać niezależnie, zapisz zmiany po każdym wierszu. Spójność bazy danych jest ważna.
Druga opcja mi się nie podoba. Byłoby dla mnie mylące (z punktu widzenia użytkownika końcowego), gdybym dokonał importu do systemu i zmniejszyłby się o 10 wierszy na 1000, tylko dlatego, że 1 jest zły. Możesz spróbować zaimportować 10, a jeśli się to nie powiedzie, spróbuj pojedynczo, a następnie zaloguj się.
Sprawdź, czy zajmuje to dużo czasu. Nie pisz „prawdopodobnie”. Jeszcze tego nie wiesz. Dopiero gdy jest to rzeczywiście problem, pomyśl o innym rozwiązaniu (marc_s).
EDYTOWAĆ
Zrobiłem kilka testów (czas w milisekundach):
10000 rzędów:
SaveChanges () po 1 wierszu: 18510,534
SaveChanges () after 100 wierszy: 4350,3075
SaveChanges () after 10000 wierszy: 5233,0635
50000 rzędów:
SaveChanges () after 1 row: 78496,929
SaveChanges () after 500 wierszy: 22302,2835
SaveChanges () after 50000 wierszy: 24022,8765
Tak więc zatwierdzenie po n wierszach jest w rzeczywistości szybsze niż w końcu.
Polecam:
- SaveChanges () po n wierszach.
- Jeśli jedno zatwierdzenie nie powiedzie się, wypróbuj je jeden po drugim, aby znaleźć wadliwy wiersz.
Klasy testowe:
STÓŁ:
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]
Klasa:
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);
}
}