本文介绍了EF Core 多导航属性产生循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下映射配置:

入门级:

entity
    .HasOne(e => e.CurrentHandling)
    .WithOne()
    .HasForeignKey<Entry>(e => e.CurrentHandlingID)
    ;

entity
    .HasMany(e => e.Handlings)
    .WithOne(h => h.Entry)
    .HasForeignKey(h => h.EntryID)
    ;

处理类:

entity
    .HasOne(h => h.Entry)
    .WithMany(e => e.Handlings)
    .HasForeignKey(h => h.EntryID)
        .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict);

企业风险管理:

当我尝试保存上下文时,出现以下异常:

When I try to save the context I get the following exception:

System.InvalidOperationException: '无法保存更改,因为在要保存的数据中检测到循环依赖项:'ForeignKey: Entry.CurrentHandlingID -> Handling.HandlingID Unique ToPrincipal: CurrentHandling, ForeignKey: Handling.EntryID -> Entry.EntryID ToDependent: 处理 ToPrincipal: Entry'.'

测试数据:

errorRepo.EnableBulkModus();

var handling = errorRepo.AddHandling(new Handling {
     CorrectedMessage = "correct",
     HandlingStatusID = 7,
     Updated = DateTime.UtcNow,
     UpdatedBy = nameof(DbInitializer)
});

var reference = errorRepo.AddReference(new Reference {
    ForeignKeyTypeID = 4,
    ForeignKeyValue = "42",
    Name = "SystemB",
    ReferenceTypeID = 6
});

var entry = errorRepo.AddEntry(new Entry {
    CurrentHandling = handling,
    DisplayMessage = "Wrong!",
    ErrorMessage = "error!",
    Inserted = DateTime.UtcNow.AddMinutes(-5),
    OriginalMessage = "incorrect",
    InsertedBy = nameof(DbInitializer),
    UUID = Guid.NewGuid(),
    Reference = reference,
    StatusID = 5
});

handling.Entry = entry;
entry.Handlings.Add(handling);

errorRepo.DisableBulkModus(true);

errorRepo.EnableBulkModus(); 仅设置一个标志,指示在调用 CommitChanges() 时不保存存储库与 errorRepo.DisableBulkModus(true); 相同,它将标志设置为 false.布尔值表示,存储库应该执行 CommitChanges().

errorRepo.EnableBulkModus(); sets just a flag which indicates the repository not to save when calling CommitChanges()Same with errorRepo.DisableBulkModus(true);, it sets the flag to false. The boolean indicated, that the repository should perform a CommitChanges().

我必须如何更改我的映射以避免循环依赖?

How do I have to change my mapping to avoid a circular dependency?

亲切的问候.

编辑 (11.03.2017)

我从处理类中删除了映射,并在入口类中添加了行 .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict):

I removed the mapping from the Handling-Class and added the line .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict) in the Entry-Class:

    entity
        .HasMany(e => e.Handlings)
        .WithOne(h => h.Entry)
        .HasForeignKey(h => h.EntryID)
        .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict)
        ;

同样的例外:

System.InvalidOperationException: '无法保存更改,因为在要保存的数据中检测到循环依赖项:'ForeignKey: Entry.CurrentHandlingID -> Handling.HandlingID Unique ToPrincipal: CurrentHandling, ForeignKey: Handling.EntryID -> Entry.EntryID ToDependent: 处理 ToPrincipal: Entry'.'

推荐答案

看到这个:

// 1.
var entry = errorRepo.AddEntry(new Entry {
    CurrentHandling = handling,
    ...
});
...
// 2.
handling.Entry = entry;

1.下面的代码需要entry接收handling的主键作为外键.下面的代码 2. 需要 handling 来将 entry 的主键恢复为 FK:鸡与蛋的问题.

The code below 1. requires entry to receive handling's primary key as foreign key. The code below 2. requires handling to reveive entry's primary key as FK: a chicken-and-egg problem.

由于handling依赖于entry(因为1-0..1的关系),所以应该先插入entry --not尚未设置其 CurrentHandling 属性.然后保存更改,以便 entry 知道其生成的 PK.然后设置 entry.CurrentHandlinghandling.Entry 并再次保存更改.

Since handling depends on entry (because of the 1-0..1 relationship), entry should be inserted first --not having its CurrentHandling property set yet. Then save changes, so entry knows its generated PK. Then set entry.CurrentHandling and handling.Entry and save changes again.

您可能希望将此代码包装在事务中.

You may want to wrap this code in a transaction.

顺便说一下,行 entry.Handlings.Add(handling); 是多余的.

By the way, the line entry.Handlings.Add(handling); is redundant.

这篇关于EF Core 多导航属性产生循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 15:23