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

问题描述

|| 我的超市模型包含一个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来获取所有StockItems:
using (var db = new MyDbContext())
{
     return db.StockItems.ToList();
}
一个处理这些项目的函数,并在另一个DbContext中添加新的Alerts:
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)将添加数据库中,尽管它已经存在! 有什么解决办法吗?     

解决方法

我认为您应该先“存货” 3英镑。 尝试这个:
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();
        }
     }
}
    ,
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的建议进行附加。