Циклическая зависимость Entity Framework для последней сущности
пожалуйста, рассмотрите следующие объекты
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
к контексту (on SaveChanges
на самом деле):
Track t = new Track("truc", Datetime.Now, pos);
ctx.Tracks.Add(t);
ctx.SaveChanges();
Я получаю следующую ошибку:
не удалось сохранить изменения, поскольку в сохраняемых данных была обнаружена циклическая зависимость: "What' {'LastTrackId'} - >'Track' {'Id'}, 'Track' {'WhatId'} - > 'What' {'Id'}'.
Я хотел сказать... да, я знаю, но...
такая конфигурация выполнима с ядром EF ?
1 ответов
это то, что я называю любимый ребенок проблема: родитель имеет несколько детей, но один из них является особенным. Это вызывает проблемы в реальной жизни... и в обработке данных.
в вашей модели класса What
(кстати, это разумное имя?) имеет Tracks
как дети, но один из них LastTrack
является особым ребенком, которому What
сохраняет ссылку.
когда как What
и Track
s создаются в одной транзакции, EF будет попробуйте использовать сгенерированный What.Id
вставить новый Track
С WhatId
. Но прежде чем он сможет спасти What
ему нужен сгенерированный идентификатор последнего Track
. Поскольку базы данных SQL не могут вставлять записи одновременно, эта циклическая ссылка не может быть установлена в одной изолированной транзакции.
вам нужна одна транзакция для сохранения What
и Track
s и последующая транзакция для установки What.LastTrackId
.
для этого в одной транскрипции базы данных вы можете обернуть код в TransactionScope
:
using(var ts = new TransactionScope())
{
// do the stuff
ts.Complete();
}
если исключение происходит, ts.Complete();
не произойдет, и откат произойдет, когда TransactionScope
удален.