Один ко многим с собой - PullRequest
       8

Один ко многим с собой

0 голосов
/ 25 сентября 2019

У меня есть такая ситуация: регулирование может быть изменено другим регламентом и может изменить другие регламенты.Или оно может быть отменено другим правилом и может отменить другие правила.

    public class Regulation
    {
        public int Id { get; set; }

        public int? AmendedByRegulationId { get; set; }
        public virtual Regulation AmendedByRegulation { get; set; }

        readonly HashSet<Regulation> amendedRegulations = new HashSet<Regulation>();
        public virtual IReadOnlyCollection<Regulation> AmendedRegulations => amendedRegulations.ToList();

        readonly HashSet<Regulation> repealedRegulations = new HashSet<Regulation>();
        public virtual IReadOnlyCollection<Regulation> RepealedRegulations => repealedRegulations.ToList();

        public void MergeAmendedRegulations(HashSet<Regulation> incomingAmendedRegulations)
        {
            if (incomingAmendedRegulations.IsNullOrEmpty())
                return;

            foreach (var dbAmendedRegulation in AmendedRegulations)
            {
                if (!incomingAmendedRegulations.Contains(dbAmendedRegulation))
                {
                    amendedRegulations.Remove(dbAmendedRegulation);
                    dbAmendedRegulation.AmendedByRegulationId = null;
                }
            }

            foreach (var amendedRegulationToAdd in incomingAmendedRegulations)
            {
                if (!amendedRegulations.Contains(amendedRegulationToAdd))
                {
                    amendedRegulations.Add(amendedRegulationToAdd);
                    amendedRegulationToAdd.AmendedByRegulationId = Id;
                }
            }
        }
    }

    /// mapping
    builder.HasOne(r => r.AmendedByRegulation)
                .WithMany(r => r.AmendedRegulations)
                .HasForeignKey(r => r.AmendedByRegulationId);

Таким образом, таблица правил содержит Id [int] not null, AmendedByRegulationId [int] null столбцы.Столбец AmendByRegulationId заполняется идентификатором поправки к Регламенту.

Регламент также загружен .Include(r => r.AmendedRegulations); Метод MergeAededRegulations () получает данные, сопоставленные с DTO, а для параметра входящего в составRegulations имеется только список идентификаторов, выбранныйиз списка.

Когда я пытаюсь сохранить, EF Core пытается вставить измененное правило, что неправильно.Он должен обновлять только свойство / столбец AmendByRegulationId.

public async Task UpdateAsync(Regulation regulation)
{
    await updateAmendedRegulations(dbContext, regulation);
    await updateRepealedRegulations(dbContext, regulation);
    await dbContext.SaveChangesAsync();
}

async Task updateAmendedRegulations(DbContext dbContext, Regulation regulation)
{
   if (regulation.AmendedRegulations.Any())
   {
        foreach (var ar in regulation.AmendedRegulations)
        {
            dbContext.Entry(ar).Property(e => e.AmendedByRegulationId).IsModified = true;
        }
        // ... other code
   }
}

Когда я вручную отмечаю свойство AmendByRegulationId как измененное, оно работает, однако

dbContext.Entry(ar)

создает исключение, если объект являетсяуже присутствует в коллекции RepealedRegulations.

Мои вопросы:

Является ли это моделирование стандартным?

Правильно ли сопоставление EF?

Как я могу исправить эти отношения с EF Core?

...