registro - linq c# tutorial español
La forma correcta de insertar varios registros en una tabla utilizando LINQ a entidades (4)
+1 por la respuesta de terryt. Necesitas seguir con el método uno o algo similar.
En la versión de Entity framework 6, hay un nuevo método para agregar un conjunto de datos en una sola declaración. Este es el método AddRange .
Me gustaría agregar que me parece que el método AddRange es elegante cuando desea agregar entidades basadas en una lista existente (o IEnumerable).
En tu caso se podría hacer algo así:
NWEntities.Products.AddRange(
Prices.Select(priceitem =>
new Product{price = priceitem})
)
Semánticamente, debe ser similar a su método 1. Un objeto de Producto se instancia por precio en la lista de precios. Sin embargo, hay una diferencia, se realiza de forma anónima, por lo que no hay variables de referencia explícitas definidas que apunten al nuevo objeto.
Si el rendimiento es importante, entonces esta pregunta podría proporcionarle más información: La forma más rápida de insertar en Entity Framework
Espero que esto te ayude.
Como muchos de nosotros hemos hecho, configuré un bucle simple para agregar varios registros desde una base de datos. Un ejemplo prototípico sería algo como esto:
Método I:
// A list of product prices
List<int> prices = new List<int> { 1, 2, 3 };
NorthwindEntities NWEntities = new NorthwindEntities();
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.AddObject(newProduct);
}
NWEntities.SaveChanges();
Sin embargo, cuando configuré el bucle por primera vez, escribí intuitivamente:
Método II:
Product newProduct = new Product();
foreach (int price in prices)
{
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
Después de leer un poco, varias personas mencionaron que si se usa el Método II, solo se agregaría un registro a la tabla. Esto parece contrario a la intuición. Es la función Agregar () la que carga una nueva inserción y, creo, crea un objeto después de cada llamada con los datos pasados. Declarar mi objeto de Producto fuera del bucle parece utilizar mejor los recursos, ya que es la única sobrecarga que se consume en cada llamada sería la reasignación de la propiedad de instancia de objeto y no la reconstrucción de la instancia de objeto en sí.
¿Alguien puede por favor aclarar? No pude encontrar otra publicación que tratara esta pregunta directamente. Si uno está ahí afuera, por favor señalo.
No necesitaríamos la ayuda de loop. Podemos hacer esto por linq. Como se indica en el siguiente código, los nombres deben agregarse a la tabla Empleado de la lista de nombres con el campo de bits IsDeleted.
db.Employee.AddRange(
nameList.Select(name =>
new Employee
{
Name = name,
IsDeleted = false
})
);
Simplemente mueva la creación de instancias del nuevo Producto dentro del bucle. Su código como está escrito agregará una sola instancia varias veces, lo que no producirá lo que está buscando ... necesita una instancia separada de cada producto ... el método Agregar no hace una copia, adjunta el objeto a la contexto y lo marca para su inserción.
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
Para ver lo que está pasando un poco más explícitamente, considere lo siguiente:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Try to reuse same Instance:");
using (var ctx = new AdventureWorksEntities())
{
List<int> ids = new List<int> {1, 2, 3};
Product p1 = new Product();
Product reference = p1;
Product p2;
Console.WriteLine("Start Count: {0}", ctx.Products.Count());
foreach (var id in ids)
{
p1.ProductID = id;
p2 = ctx.Products.Add(p1);
Console.WriteLine("p1 = p2 ? {0}", p1 == p2);
Console.WriteLine("p2 = reference? {0}", p2 == reference);
Console.WriteLine("State: {0}", ctx.Entry(p1).State);
var changes = ctx.ChangeTracker.Entries<Product>();
Console.WriteLine("Change Count: {0}", changes.Count());
}
}
Console.WriteLine();
Console.WriteLine("Distinct Instances:");
using (var ctx = new AdventureWorksEntities())
{
List<int> ids = new List<int> { 1, 2, 3 };
Product p2;
foreach (var id in ids)
{
var p1 = new Product {ProductID = id};
p2 = ctx.Products.Add(p1);
Console.WriteLine("p1 = p2 ? {0}", p1 == p2);
Console.WriteLine("State: {0}", ctx.Entry(p1).State);
var changes = ctx.ChangeTracker.Entries<Product>();
Console.WriteLine("Change Count: {0}", changes.Count());
}
}
Console.ReadLine();
}
}
En el primer ciclo, está reutilizando la misma instancia del producto, pero cuando lo agrega al contexto, solo está usando la misma referencia cada vez. Puede ver que el recuento de cambios permanece en 1 independientemente de cuántas veces se ejecute el bucle. Por supuesto, solo se guardarán los últimos valores si tuviera que llamar a ctx.SaveChanges ().
En la segunda versión, el recuento de cambios se incrementa correctamente cada vez y al llamar a SaveChanges se guardarán todas las entidades distintas como cabría esperar.
Tuve un problema similar. En mi edición, tenía este código:
var cratelist = db.TruckContainerLoads.Where(x => x.TruckID == truckid).Select(x => x.ContainerID);
if (!cratelist.Any())
{
return;
}
foreach (var crateid in cratelist) {
TruckContainerLoad crInstance = new TruckContainerLoad();
crInstance.ContainerID = crateid;
try
{
db.TruckContainerLoads.Add(crInstance);
db.SaveChanges();
}
catch
{
return;
}
}
Mi consulta solo agregó el primer registro en mi foreach. El problema era que necesitaba llamar a mi db.SaveChanges () fuera del bucle foreach, después de agregar varios registros. Para mí, la respuesta a mi problema estaba realmente en la pregunta. Entonces, estoy votando la pregunta.