实体框架核心 - 不需要的删除级联

时间:2017-12-20 10:01:04

标签: c# .net-core entity-framework-core

我有实体框架核心,它执行我不想要的额外删除。

模型定义:我有两个实体TemplateTemplateVersionTemplateVersion只是模板的下一个版本,因此TemplateVersion只有一个Template(N:1关系)

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

public class TemplateVersion
{
    public int Id { get; set; }
    public Template Template { get;set; }
}

到目前为止,一切都很清楚。

但是:我希望获得Template级别的信息,这是TemplateVersion的当前版本,因此我的Template定义现在看起来像{{{ 1}}和以前一样)

TemplateVersion

所以我希望public class Template { public int Id { get; set; } public TemplateVersion CurrentVersion { get; set;} } NTemplateVersion个实例指向1的{​​{1}}实例,但同时Template指的是Template 1 TemplateVersion

这里的魔术开始了:当我添加一个Template和一个TemplateVersion时,一切都运转良好。

Template ---- TemplateVersionPrevious.Template == Template

但当我添加另一个TemplateVersion实例指向同一个Template(并更新Template的{​​{1}})时,CurrentVersion的第一个实例突然出现它的TemplateVersion字段为空。

Template

我认为这是因为实体框架认为我有一个经典的Template ---- TemplateVersionPrevious.Template == null ---- TemplateVersionCurrent.Template == Template 关系,只有1:1的一个实例可以与同一个TemplateVersion有关系 - 这是因为{ {1}}字段。

如何告诉Entity Framework它不应该清除我的Template关系?

其他信息:我将CurrentTemplate实体定义如下

TemplateVersion

它变得更有趣:TemplateVersion的上一个实例刚刚被删除!

public class TemplateVersion
{
    public int Id { get; set; }
    [ForeignKey(nameof(TemplateId))]
    public Template Template { get;set; }
    public int TemplateId {get;set;}
}

1 个答案:

答案 0 :(得分:6)

EF默认约定不适用于2个实体之间的多个关系。并且数据注释不能很好地与一对一关系或单向关联(在一端没有导航属性的关系)。

您需要使用流畅的API显式配置所需的关系。由于流畅的API对于具有/不具有导航属性具有不同的重载并且用于纠正过载很重要,所以假设您的模型与此完全相同(我的意思是导航和显式FK属性影响关系,其他属性无关紧要):

public class Template 
{
    public int Id { get; set; }
    public TemplateVersion CurrentVersion { get; set; }
}

public class TemplateVersion
{
    public int Id { get; set; }
    public Template Template { get; set; }
}

所需两种关系的流畅配置如下:

modelBuilder.Entity<Template>()
    .HasMany<TemplateVersion>()
    .WithOne(e => e.Template)
    .IsRequired();

modelBuilder.Entity<Template>()
    .HasOne(e => e.CurrentVersion)
    .WithOne()
    .HasForeignKey<Template>("TemplateVersionId")
    .IsRequired(false);

请注意,您已定义了循环关系,因此其中一个应该是可选的。我选择Template..TemplateVersionId作为我认为合乎逻辑的选择。

另请注意,对于一对一关系,主要和从属目标不能从HasOne / WithOne唯一确定,因此您需要使用HasForeignKey和{{1 泛型类型参数来指定(相反,一对多关系没有这样的问题,因为一方总是主要的,而manu方是依赖的)。

有关详细信息,请参阅Relationships