[英]Entity Framework 6 Upsert
我正在嘗試使用實體框架的最新文章。 我有以下代碼拋出錯誤:
using (var db = new Entities.DB.DConn())
{
//...
foreach (Account account in accounts)
{
Entities.DB.Account dlAccount = new Entities.DB.Account();
dlAccount.GId = dlG.Id;
dlAccount.AccountName = account.NameAtFI;
dlAccount.AccountNumber = account.AcctNumber;
dlAccount.AcctType = account.AcctType;
dlAccount.AsOfDate = account.DateCreated;
dlAccount.IsDeleted = false;
dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime();
db.Entry(dlAccount).State = ((dlAccount.GId == dlG.Id) ? EntityState.Modified : EntityState.Added);
db.SaveChanges();
}
}
例外:
存儲更新,插入或刪除語句影響了意外的行數(0)。 自加載實體以來,實體可能已被修改或刪除。
本質上,我想做的就是更新記錄, if dlAccount.GId == dlG.Id
或插入它(如果不存在)。 以下代碼無需使用EntityState即可實現我想要的功能:
using (var db = new Entities.DB.DConn())
{
//...
foreach (Account account in accounts)
{
bool isNewRecord = false;
Entities.DB.Account dlAccount = new Entities.DB.Account();
Entities.DB.Account exisitngAcct = db.Accounts.Where(x => x.GId == dlG.Id).FirstOrDefault(); //x.GId is NOT ad primary key
if (exisitngAcct != null)
{
dlAccount = exisitngAcct;
isNewRecord = true;
}
dlAccount.GId = dlG.Id;
dlAccount.AccountName = account.NameAtFI;
dlAccount.AccountNumber = account.AcctNumber;
dlAccount.AcctType = account.AcctType;
dlAccount.AsOfDate = account.DateCreated;
dlAccount.IsDeleted = false;
dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime();
if (isNewRecord)
{
dldb.Accounts.Add(dlAccount);
}
db.SaveChanges();
}
}
有人可以在這里看到我可能做錯的任何事情嗎? 我真的很想讓這個工作正常,避免像上面那樣使用過大的代碼。
TIA
首先,我應該指出,您發布的(非EntityState)示例中的邏輯看起來並不像我期望的那樣-至少基於我的理解,這可能是錯誤的:)
*免責聲明-我已經在文本編輯器中修改了此內容,請原諒所有錯誤。
如果我們以此為您的要求:
本質上,我想做的就是更新記錄,如果dlAccount.GId == dlG.Id或插入它(如果不存在)。
然后,我希望非EntityState版本看起來像這樣:
using (var db = new Entities.DB.DConn())
{
//...
foreach (Account account in accounts)
{
Entities.DB.Account dlAccount = null;
Entities.DB.Account exisitngAcct = db.Accounts.Where(x => x.GId == dlG.Id).FirstOrDefault(); //x.GId is NOT ad primary key
if (exisitngAcct != null)
{
//If there is an EXISTING account, it will already be tracked by EF so no need to attach it.
dlAccount = exisitngAcct;
}
else
{
//No account exists, so we need to create one, and ADD it to our EF context as a new Entity
dlAccount = new Entities.DB.Account();
db.Accounts.Add(dlAccount);
}
dlAccount.GId = dlG.Id;
dlAccount.AccountName = account.NameAtFI;
dlAccount.AccountNumber = account.AcctNumber;
dlAccount.AcctType = account.AcctType;
dlAccount.AsOfDate = account.DateCreated;
dlAccount.IsDeleted = false;
dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime();
db.SaveChanges();
}
}
假設以上是您所需要的,並且還假設我們有充分的理由不僅僅使用上述的EF跟蹤,那么手動處理EF狀態將如下所示:
using (var db = new Entities.DB.DConn())
{
//...
foreach (Account account in accounts)
{
Entities.DB.Account exisitngAcct = db.Accounts.FirstOrDefault(x => x.GId == dlG.Id).FirstOrDefault(); //x.GId is NOT ad primary key
//NB. Since we're already pulling up the record with EF, there is *probably* no measurable advantage in not just using EF tracking at this point (unless this is a HUUUGE list of objects)
// in which case we should use the .AsNoTracking() modifier when we load the records (and they should be loaded in batches/all at once, to reduce DB hits)
Entities.DB.Account dlAccount = new Entities.DB.Account();
if(exisitngAcct == null)
{
db.Entry(dlAccount).State = EntityState.Added;
}
else
{
dlAccount.Id = exisitngAcct.Id; //We have to set the PK, so that EF knows which object to update
db.Entry(dlAccount).State = EntityState.Modified;
}
dlAccount.GId = dlG.Id;
dlAccount.AccountName = account.NameAtFI;
dlAccount.AccountNumber = account.AcctNumber;
dlAccount.AcctType = account.AcctType;
dlAccount.AsOfDate = account.DateCreated;
dlAccount.IsDeleted = false;
dlAccount.DateModified = DateTime.UtcNow.ToUniversalTime();
db.SaveChanges();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.