Je voudrais d'abord tester pour en être sûr. La Performance ne doit pas être si mauvais que ça.
Si vous avez besoin de saisir toutes les lignes en une seule transaction, de l'appeler après tout de AddToClassName classe. Si les lignes peuvent être saisies de façon indépendante, d'enregistrer les modifications après chaque ligne. La consistance de la base de données est important.
Deuxième option, je n'aime pas. Il serait source de confusion pour moi (à partir de finale de vue de l'utilisateur) si j'ai fait l'importation de système et il y aurait une diminution de 10 lignes de 1000, juste parce que 1 est mauvais. Vous pouvez essayer d'importer 10 et si elle échoue, essayer un par un et puis connectez-vous.
Tester si ça prend beaucoup de temps. Ne pas écrire 'probablement'. Vous ne le connaissez pas encore. Seulement quand il est en fait un problème, de penser à autre solution (marc_s).
MODIFIER
J'ai fait quelques tests (temps en millisecondes):
10000 lignes:
SaveChanges() après 1 ligne:18510,534
SaveChanges() après 100 lignes:4350,3075
SaveChanges() après 10000 lignes:5233,0635
50000 lignes:
SaveChanges() après 1 ligne:78496,929
SaveChanges() après 500 lignes:22302,2835
SaveChanges() après 50000 lignes:24022,8765
Donc, il est effectivement plus rapide de s'engager après la n de lignes que, après tout.
Ma recommandation est de:
- SaveChanges() après n lignes.
- Si un commit échoue, essayer un par un pour trouver défectueux ligne.
Classes de Test:
TABLEAU:
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);
}
}