正如我们许多人所做的那样,我设置了一个简单的循环来从数据库中添加多条记录。一个典型的例子是这样的:
方法一:
// 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();
然而,当我第一次设置循环时,我凭直觉写道:
方法二:
Product newProduct = new Product();
foreach (int price in prices)
{
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
在阅读了一些内容后,一些人提到如果使用方法二,只会向表中添加一条记录。这似乎违反直觉。加载新插入的是 Add() 函数,而且我认为,在每次调用传入的数据后创建一个对象。在循环外部声明我的 Product 对象似乎可以更好地利用资源,因为每次调用中消耗的唯一开销是对象实例属性的重新分配,而不是对象实例本身的重建。
谁能解释一下?我找不到另一篇直接处理这个问题的帖子。如果有,请指出。
最佳答案
只需将新产品的实例化移动到循环内即可。您编写的代码将多次添加一个实例,这不会产生您想要的东西......您需要每个产品的单独实例...... Add 方法不会制作副本,它将对象附加到上下文并将其标记为插入。
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
要更明确地了解正在发生的事情,请考虑以下内容:
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();
}
}
在第一个循环中,您重复使用了相同的产品实例,但是当您将它添加到上下文中时,您每次都只是使用相同的引用。您可以看到无论循环执行了多少次,更改计数都保持为 1。当然,如果您要调用 ctx.SaveChanges(),只会保存最后的值。
在第二个版本中,更改计数每次都会正确递增,您将调用 SaveChanges 来保存所有不同的实体,正如您所期望的那样。
关于c# - 使用 LINQ to Entities 向表中插入多条记录的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22489118/