Primero lo probaría para estar seguro. El rendimiento no tiene por qué ser tan malo.
Si necesita ingresar todas las filas en una transacción, llámelo después de toda la clase AddToClassName. Si las filas se pueden ingresar de forma independiente, guarde los cambios después de cada fila. La consistencia de la base de datos es importante.
Segunda opción que no me gusta. Sería confuso para mí (desde la perspectiva del usuario final) si hiciera una importación al sistema y disminuiría 10 filas de 1000, solo porque 1 es malo. Puede intentar importar 10 y, si falla, intente uno por uno y luego inicie sesión.
Prueba si lleva mucho tiempo. No escriba "propagable". Aún no lo sabes. Solo cuando sea realmente un problema, piense en otra solución (marc_s).
EDITAR
He hecho algunas pruebas (tiempo en milisegundos):
10000 filas:
SaveChanges () después de 1 fila: 18510,534
SaveChanges () después de 100 filas: 4350,3075
SaveChanges () después de 10000 filas: 5233,0635
50000 filas:
SaveChanges () después de 1 fila: 78496,929
SaveChanges () después de 500 filas: 22302,2835
SaveChanges () después de 50000 filas: 24022,8765
Entonces, en realidad, es más rápido comprometerse después de n filas que después de todo.
Mi recomendación es:
- SaveChanges () después de n filas.
- Si falla una confirmación, inténtelo uno por uno para encontrar la fila defectuosa.
Clases de prueba:
MESA:
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]
Clase:
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);
}
}