最后一个实体的实体框架循环依赖

tsc*_*007 9 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; }
}
Run Code Online (Sandbox Code Playgroud)

我使用以下命令配置实体:

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);
Run Code Online (Sandbox Code Playgroud)

你有没有看到有一个想要的循环参考:

What.LastTrack <-> Track.What
Run Code Online (Sandbox Code Playgroud)

当我尝试添加一个Track上下文(SaveChanges实际上是):

Track t = new Track("truc", Datetime.Now, pos);
ctx.Tracks.Add(t);
ctx.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

无法保存更改,因为在要保存的数据中检测到循环依赖关系:''什么'{'LastTrackId'} - >'跟踪'{'Id'},'跟踪'{'WhatId'} - >'什么' {'ID'}'.

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

这样的配置是否适用于EF Core?

Ger*_*old 15

这就是我喜欢称之为青睐的孩子问题:父母有多个孩子,但其中一个是特别的.这会导致现实生活中的问题......以及数据处理中的问题.

在你的班级模型中,What(顺便说一下,这是一个明智的名字吗?)Tracks作为孩子,但其中一个,LastTrack是一个特殊的孩子,What作为参考.

当在一个事务中创建两者WhatTracks时,EF将尝试使用生成What.Id的插入新的Tracks WhatId.但在它可以保存What之前需要生成最后一个Id Track.由于SQL数据库无法同时插入记录,因此无法在一个独立的事务中建立此循环引用.

您需要一个要保存的事务What及其Tracks和要设置的后续事务What.LastTrackId.

要在一个数据库传输中执行此操作,您可以将代码包装在TransactionScope:

using(var ts = new TransactionScope())
{
    // do the stuff
    ts.Complete();
}
Run Code Online (Sandbox Code Playgroud)

如果发生异常,ts.Complete();则不会发生,并且在处理异常时将发生回滚TransactionScope.