最後一個實體的實體框架循環依賴

entity-framework entity-framework-core

請考慮以下實體

public class What {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Track> Tracks { get; set; }
    public int? LastTrackId { get; set; }]
    public Track LastTrack { get; set; }
}

public class Track {
    public Track(string what, DateTime dt, TrackThatGeoposition pos) {
        What = new What { Name = what, LastTrack = this };
    }

    public int Id { get; set; }

    public int WhatId { get; set; }
    public What What { get; set; }
}

我使用以下命令配置實體:

builder.HasKey(x => x.Id);
builder.HasMany(x => x.Tracks).
    WithOne(y => y.What).HasForeignKey(y => y.WhatId);
builder.Property(x => x.Name).HasMaxLength(100);
builder.HasOne(x => x.LastTrack).
    WithMany().HasForeignKey(x => x.LastTrackId);

你有沒有看到有一個想要的循環參考:

What.LastTrack <-> Track.What

當我嘗試向上下文添加一個Track (事實上在SaveChanges上):

Track t = new Track("truc", Datetime.Now, pos);
ctx.Tracks.Add(t);
ctx.SaveChanges();

我收到以下錯誤:

無法保存更改,因為在要保存的數據中檢測到循環依賴關係:''What'{'LastTrackId'} - >'Track'{'Id'},'Track'{'WhatId'} - >'What' {'ID'}'。

我想說...是的,我知道但......

這樣的配置是否適用於EF Core?

一般承認的答案

這就是我喜歡稱之為青睞的孩子問題:父母有多個孩子,但其中一個是特別的。這會導致現實生活中的問題......以及數據處理中的問題。

在你的班級模型中, WhatWhat是一個明智的名字,順便說一下?)將Tracks作為孩子,但其中一個, LastTrack是一個特殊的孩子, What保留了參考。

當在一個事務中創建了WhatTrack ,EF將嘗試使用生成的What.Id插入具有WhatId的新Track 。但在此之前它可以節省What需要最後的生成的ID Track 。由於SQL數據庫無法同時插入記錄,因此無法在一個獨立的事務中建立此循環引用。

您需要一個事務來保存What及其Track和後續事務來設置What.LastTrackId

要在一個數據庫轉換中執行此操作,您可以將代碼包裝在TransactionScope

using(var ts = new TransactionScope())
{
    // do the stuff
    ts.Complete();
}

如果發生異常,則ts.Complete();將不會發生,並且在TransactionScope時將發生回滾。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow