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

发布于 2024-11-09 08:32:27 字数 967 浏览 0 评论 0原文

我的超市模型包含一个 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)将被添加到数据库中,尽管它已经存在! 有什么解决办法吗?

my supermarket model contains a StockItem class and an Alert class which contains a StockItem field:

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; }
}

I Have a function that fetches all StockItems with one DbContext:

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

And another function that process these items, and adding new Alerts in a another 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();
        }
     }
}

The problem is: When an Alert is Saved, a new Stock Item (with a different id) is added to the database, although it is already there!
any solutions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

她比我温柔 2024-11-16 08:32:27

我认为您应该首先附加库存商品。
试试这个:

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();
        }
     }
}

I think you should Attach the stockitem first.
Try this:

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();
        }
     }
}
怂人 2024-11-16 08:32:27
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 使所有库存项目成为独立的(分离项目),并且当您将它们添加到不同的上下文时,上下文假设它是一项新项目,它将插入该项目。

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

否则你必须按照本的建议附加。

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();
      }
   }        
}

In this case you dont need to do attach. EF can only track changes in its own life cycle, in your first case when you do,

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

You are disposing MyDbContext, so EF makes all stock items as independent (detached items), and when you add them to different context, context assumes that it is a new item and it will insert the one.

The best way will be to keep Context alive throughout the changes you want to make. Also note, keeping context alive for longer time does not mean you will keep database connection open all the time. EF will open and close database connection automatically only when you are executing query and you are calling save changes.

Otherwise you have to attach as Ben suggested.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文