ho iniziato ad esaminare in primo luogo per essere sicuro. Le prestazioni non devono essere così male.
Se è necessario immettere tutte le righe in una transazione, chiamarla dopo tutta la classe AddToClassName. Se le righe possono essere inserite indipendentemente, salvare le modifiche dopo ogni riga. La consistenza del database è importante.
Seconda opzione non mi piace. Sarebbe fonte di confusione per me (dal punto di vista dell'utente finale) se avessi importato nel sistema e avrebbe declinato 10 righe su 1000, solo perché 1 è negativo. Puoi provare a importare 10 e se fallisce, prova uno per uno e poi loggati.
Test se richiede molto tempo. Non scrivere "propably". Non lo sai ancora. Solo quando è effettivamente un problema, pensa ad un'altra soluzione (marc_s).
EDIT
Ho fatto alcuni test (tempo in millisecondi):
10000 righe:
SaveChanges() dopo 1 fila: 18510,534
SaveChanges() dopo 100 righe: 4350,3075
SaveChanges() dopo 10000 righe: 5233,0635
50000 righe:
SaveChanges() dopo il 1 ° fila: 78496,929
SaveChanges() dopo 500 righe: 22302,2835
SaveChanges() dopo 50000 Righe: 24022,8765
quindi è effettivamente più veloce di commettere dopo n file che dopo tutto.
mia raccomandazione è di:
- SaveChanges() dopo n righe.
- Se un commit fallisce, provatelo uno per uno per trovare una riga difettosa.
classi di test:
TABELLA:
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]
Classe:
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);
}
}
La ragione per cui ho scritto "probabilmente" è che ho fatto un'ipotesi plausibile. Per rendere più chiaro che "Non sono sicuro", ho fatto una domanda. Inoltre, penso che abbia perfettamente senso pensare a potenziali problemi PRIMA di incontrarli. Questa è la ragione per cui ho fatto questa domanda. Speravo che qualcuno sapesse quale metodo sarebbe più efficiente, e potrei andare con quello, subito. –
Tizio fantastico. Esattamente quello che stavo cercando. Grazie per aver dedicato del tempo per testare questo! Immagino di poter immagazzinare ogni lotto in memoria, provare il commit, e poi se fallisce, passa a ciascuno di essi individualmente come hai detto tu. Quindi, una volta completato il batch, rilasciare i riferimenti a quei 100 elementi in modo che possano essere eliminati dalla memoria. Grazie ancora! –
La memoria non verrà liberata, poiché tutti gli oggetti saranno trattenuti da ObjectContext, ma in questo momento il contesto non richiede molto spazio in 50000 o 100000. – LukLed