最后一个实体的实体框架循环依赖 [英] Entity Framework circular dependency for last entity
问题描述
请考虑以下实体
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 Track
s are created in one transaction, EF will try to use the generated What.Id
to insert the new Track
s 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 Track
s 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屋!