实体框架SaveChanges()在不同的DbContext中插入不必要的行

时间:2011-05-24 07:41:33

标签: entity-framework entity savechanges

我的超市模型包含一个StockItem类和一个包含StockItem字段的Alert类:

public class StockItem
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int CurrentQuantity { get; set; }
    public int MinQuantity { get; set; }
}

public class Alert
{
    public int ID { get; set; }
    public int Message{ get; set; }
    public virtual StockItem StockItem { get; set; }
}

我有一个函数可以使用一个DbContext获取所有StockItem:

using (var db = new MyDbContext())
{
     return db.StockItems.ToList();
}

另一个处理这些项目的函数,并在另一个DbContext中添加新的警报:

foreach (var item in items)
{
     if (item.CurrentQuantity < item.MinQuantity)
     {
        using (var db = new MyDbContext())
        {
            db.Alerts.Add(new Alert(){StockItem = item, Message = "Low Quantity"});
            db.SaveChanges();
        }
     }
}

问题是:当保存警报时,会向数据库添加一个新的库存项目(具有不同的ID),尽管它已经存在! 任何解决方案?

2 个答案:

答案 0 :(得分:5)

我认为你应该Attach首先使用stockitem。 试试这个:

foreach (var item in items)
{
     if (item.CurrentQuantity < item.MinQuantity)
     {
        using (var db = new MyDbContext())
        {
            db.StockItems.Attach(item);
            db.Alerts.Add(new Alert {StockItem = item, Message = "Low Quantity"});
            db.SaveChanges();
        }
     }
}

答案 1 :(得分:0)

using (var db = new MyDbContext())
{
   var items = db.StockItems.ToList();
   foreach (var item in items)
   {
      if (item.CurrentQuantity < item.MinQuantity)
      {
         db.Alerts.Add(new Alert {StockItem = item, 
            Message = "Low Quantity"});
         db.SaveChanges();
      }
   }        
}

在这种情况下,你不需要做附件。 EF只能跟踪你自己生命周期中的变化,在你做的第一种情况下,

using (var db = new MyDbContext())
{
     return db.StockItems.ToList();
}

您正在处置MyDbContext,因此EF将所有库存项目视为独立项目(分离项目),并且当您将它们添加到不同的上下文时,上下文假定它是一个新项目并且它将插入该项目。

最好的方法是在您想要进行的更改中保持Context活跃。另请注意,将上下文保持较长时间并不意味着您将始终保持数据库连接处于打开状态。只有在执行查询并且您正在调用保存更改时,EF才会自动打开和关闭数据库连接。

否则你必须像Ben建议的那样附上。