最后一个实体的实体框架循环依赖 [英] Entity Framework circular dependency for last entity

查看:134
本文介绍了最后一个实体的实体框架循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下实体

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; }
}

我使用以下内容配置实体:

I use the following to configure the entities:

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);

您可以看到有通缉的通函吗?

Has you can see there is a wanted circular reference:

What.LastTrack <-> Track.What

c>到上下文(实际上在 SaveChanges 上):

when I try to add a Track to the context (on SaveChanges in fact):

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

我收到以下错误:


无法保存更改,因为在要保存的数据中检测到循环依赖性:''What'{'LastTrackId'}->'Track'{'Id'},'Track'{'WhatId '}->'What'{'Id'}'。

Unable to save changes because a circular dependency was detected in the data to be saved: ''What' {'LastTrackId'} -> 'Track' {'Id'}, 'Track' {'WhatId'} -> 'What' {'Id'}'.

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

I would like to say... yes, I know but...

这样的配置对EF Core可行吗?

Is such a configuration doable with EF Core ?

推荐答案

这就是我喜欢的最喜欢的孩子问题:父母有多个孩子,但是其中一个特别特殊。

This is what I like to call the favored child problem: a parent has multiple children, but one of them is extra special. This causes problems in real life... and in data processing.

在您的类模型中,什么(是(一个明智的名称,对吗?)将 Tracks 作为孩子,但是其中一个 LastTrack 是特殊的孩子什么保持引用。

In your class model, What (is that a sensible name, by the way?) has Tracks as children, but one these, LastTrack is the special child to which What keeps a reference.

两者都什么 Track 是在一次交易中创建的,EF将尝试使用生成的 What.Id 插入新的使用 WhatId 跟踪。但是在保存什么之前,它需要最后一个 Track 生成的ID。由于SQL数据库无法同时插入记录,因此无法在一个独立的事务中建立此循环引用。

When both What and Tracks are created in one transaction, EF will try to use the generated What.Id to insert the new Tracks with WhatId. But before it can save What it needs the generated Id of the last Track. Since SQL databases can't insert records simultaneously, this circular reference can't be established in one isolated transaction.

您需要一个事务来保存什么及其 Track 和随后的设置 What.LastTrackId 的交易。

You need one transaction to save What and its Tracks and a subsequent transaction to set What.LastTrackId.

要在一个数据库事务中执行此操作,可以将代码包装在 TransactionScope

To do this in one database transcation you can wrap the code in a TransactionScope:

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

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

If an exception occurs, ts.Complete(); won't happen and a rollback will occur when the TransactionScope is disposed.

这篇关于最后一个实体的实体框架循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆