EF Core的多个导航属性产生循环依赖 [英] EF Core multiple navigation properties produce circular dependency

查看:136
本文介绍了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);

ERM:

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

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

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

System.InvalidOperationException: 'Unable to save changes because a circular dependency was detected in the data to be saved: 'ForeignKey: Entry.CurrentHandlingID -> Handling.HandlingID Unique ToPrincipal: CurrentHandling, ForeignKey: Handling.EntryID -> Entry.EntryID ToDependent: Handlings 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唯一ToPrincipal:CurrentHandling,ForeignKey:Handling.EntryID-> Entry.EntryID ToDependent:处理ToPrincipal:Entry'.'

System.InvalidOperationException: 'Unable to save changes because a circular dependency was detected in the data to be saved: 'ForeignKey: Entry.CurrentHandlingID -> Handling.HandlingID Unique ToPrincipal: CurrentHandling, ForeignKey: Handling.EntryID -> Entry.EntryID ToDependent: Handlings 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.

由于处理取决于 entry (由于1-0..1关系),因此应先插入 entry ,而不是设置了 CurrentHandling 属性.然后保存更改,以便 entry 知道其生成的PK.然后设置 entry.CurrentHandling handling.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的多个导航属性产生循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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