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



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

模型定义:我有两个实体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定义现在看起来像(TemplateVersion和以前一样)

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

所以我想要的是NTemplateVersion实例指向1Template实例,但同时Template指向1TemplateVersion

魔术从这里开始:当我添加一个Template和一个TemplateVersion一切都很好。

Template ---- TemplateVersionPrevious.Template == Template

但是当我添加另一个指向同一TemplateTemplateVersion实例(并更新TemplateCurrentVersion)时,突然TemplateVersion的第一个实例的Template字段为空。

Template ---- TemplateVersionPrevious.Template == null
---- TemplateVersionCurrent.Template == Template

我相信这是因为实体框架认为我有一个经典的1:1关系,并且只有一个TemplateVersion实例可以与同一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;}
}

它变得更加有趣:以前的TemplateVersion实例刚刚被删除!

Template ---- TemplateVersionCurrent.Template == Template

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唯一确定,因此您需要使用HasForeignKeyHasPrinciplaKey泛型类型参数来指定(相比之下,一对多关系没有这样的问题,因为一方始终是主方,而 manu 方是依赖方)。

有关详细信息,请参阅关系。

最新更新