簡體   English   中英

實體框架6 Upsert

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM