簡體   English   中英

EF更新關系的子關系

[英]EF update the child relation of a relation

EF跟蹤使我感到困惑。 這是我正在嘗試實現的方案:

public class CentralPoint
{
   public Guid ID { get; set; }
   public virtual BIDatabase BIDatabase { get; set; }
}

public class BIDatabase
{
    public Guid ID { get; set; }
    public Guid CentralPointID { get; set; }
    public virtual CentralPoint CentralPoint { get; set; }
    public Guid ConnectionID { get; set; }
    public virtual Connection Connection { get; set; }
}

public class Connection
{
    public Guid ID { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

這些是我的實體模型。 我在CentralPointBIDatabase實體之間BIDatabase一對一關系,在BIDatabaseConnection實體之間也存在一對一關系。 顯然,每個實體都有一個單獨的表。

在控制器內部,我正在使用新實例更新CentralPointBIDatabase屬性。

centralPoint.BIDatabase = biDatabase;

這是控制器部分:

public async Task<IActionResult> AddBIDatabaseAsync(Guid cpId, BIDatabase biDatabase)
    {
       // context is available through Dependency Injection (.net core)
        var centralPoint = _context.CentralPoint.Where(cp => cp.ID == cpId)
            .Include(cp => cp.BIDatabase)
            .ThenInclude(biDb => biDb.Connection)
            .FirstOrDefault();

        centralPoint.BIDatabase = biDatabase;
        await _context.SaveChangesAsync();

        // more code ...
    }

在這之后:

CentralPoint表->保持不變:正常

BIDatabase表->更新為新ID:正常

連接表-> //添加新行,而不是更新舊行

我想要的是對同一數據庫每次都更新而不是每次添加的連接實體。

我看到了問題。

當您替換centralPoint.BIDatabase = biDatabase; 您的新BIDatabase對象可能沒有將其鏈接到Connection的ID

嘗試將所需的字段映射到現有對象上,而不是替換它(或替換它,但首先將要持久化的所有Id和現有字段映射到新對象上)。

什么代碼創建了這個新的biDatabase? 在此方法之前,它是否一直保留到dbContext?

您對BIDatabase和連接表的期望有點可疑。 給定現有的CentralPoint / w BIDatabase / w連接,如果將CentralPoint的BIDatabase“更改”為新的,則現有記錄不會更新,它將被替換。 這意味着將刪除舊記錄及其關聯的連接,並插入新的BIDatabase / wa new Connection。 假設使用數據庫生成的密鑰配置了這些實體:

示例:CentralPoint(id:1)-> BIDatabase(id:1)-> Connection(id:1)

使用新的連接(id:x)創建新的BIDatabase(id:x),然后:

CentralPoint.BIDatabase = newBIDatabase

BIDatabase(id:1)和Connection(id:1)被標記為刪除。 保存時,新的BIDatabase&Connection將保留新的ID。

CentralPoint(id:1)-> BIDatabase(id:2)-> Connection(id:2)

如果要替換BIDatabase但要保留相同的連接ID /引用,請執行以下操作:

創建新的BIDatabase(id:x)/ w Connection(id:x)

但在將其保存到上下文之前:

   var centralPoint = _context.CentralPoint.Where(cp => cp.ID == cpId)
        .Include(cp => cp.BIDatabase)
        .ThenInclude(biDb => biDb.Connection)
        .FirstOrDefault();

   biDatabase.Connection = (centralPoint?.BIDatabase?.Connection) ?? biDatabase.Connection;

    centralPoint.BIDatabase = biDatabase;
    await _context.SaveChangesAsync();

該額外語句的作用是通過將引用復制到新的BIDatabase來保留現有CentralPoint.BIDatabase上已有的現有連接。 如果現有的BIDatabase沒有連接(或現有的CP沒有BIDatabase),則將使用創建的新連接。 如果沒有在此代碼之前將新的BIDatabase保存到dbContext,則“新”連接(id:x)將永遠不會插入到替換現有BIDatabase的位置。

我在犯一些錯誤。 我正在詳細說明它們,因此可能會對其他人有所幫助。

第一個錯誤 (由@ Steveland83指出)

centralPoint.BIDatabase = biDatabase;

由於上下文(DbContext)跟蹤了CentralPoint實體,因此我們不能簡單地用另一個屬性來替換。 我們需要通過復制值來修改屬性。 因此,應改為執行以下操作

_context.Entry(centralPoint.BIDatabase).CurrentValues.SetVal的UE(biDatabase);

第二個錯誤通過上面的修復,我希望上下文能夠跟蹤centralPoint.BIDatabase中的所有屬性更改,並自行進行更新(在我的情況下為Connection屬性,例如centralPoint.BIDatabase.Connection)。

但是,不幸的是,這對於非原始類型不會發生。 您必須明確地告訴上下文哪些非原始屬性已更改。 這是第二個解決方法

_context.Entry(centralPoint.BIDatabase).CurrentValues.SetVal的UE(biDatabase);

_context.Entry(centralPoint.BIDatabase.Connection).CurrentValues.SetVal的UE(biDatabase.Connection);

這將使用更改來更新BIDatabase和Connection表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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