Entity framework SaveChanges() in a different DbContext inserting unnecessary rows
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?
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();
}
}
}
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.
精彩评论