简体   繁体   English

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

[英]Entity Framework Core - unwanted delete cascade

I have Entity Framework Core which performs additional delete which I don't want. 我有实体框架核心,它执行我不想要的额外删除。

Model definition: I have two entities Template and TemplateVersion . 模型定义:我有两个实体TemplateTemplateVersion A TemplateVersion are just next versions of template, so TemplateVersion has one Template (N:1 relation) TemplateVersion只是TemplateVersion的下一个版本,因此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; }
}

And up to now all is clear an working good. 到目前为止,一切都清楚是一种有益的工作。

BUT : I want to have information on Template level which is the current version of TemplateVersion , so my Template definition now looks like ( TemplateVersion is the same as before) 但是 :我想有信息Template水平,这是当前版本的TemplateVersion ,所以我的Template定义现在的样子( TemplateVersion是和以前一样)

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

So what I want to have is N instances of TemplateVersion to point to 1 instance of Template but in the same time Template is pointing to 1 TemplateVersion 所以我想要的是TemplateVersion N实例指向1Template实例,但同时Template指向1 TemplateVersion

And here the magic starts: when I add one Template and one TemplateVersion all is working good. 这里的魔术开始了:当我添加一个Template和一个TemplateVersion一切都运行良好。

Template ---- TemplateVersionPrevious.Template == Template

But when I add another instance of TemplateVersion pointing to the same Template (and update Template 's CurrentVersion ) suddenly first instance of TemplateVersion has its Template field nulled. 但是,当我添加指向同一Template另一个TemplateVersion实例(并更新TemplateCurrentVersion )时, TemplateVersion第一个实例突然将其Template字段置为空。

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

I believe that it's because Entity Framework is thinking that I have a classic 1:1 relation and only one instance of TemplateVersion can have relation to the same Template - and it's because of CurrentTemplate field. 我相信这是因为实体框架认为我有一个经典的1:1关系,并且只有一个TemplateVersion实例可以与同一个Template有关系 - 而且这是因为CurrentTemplate字段。

How can I tell Entity Framework that it should not clear my TemplateVersion relation? 如何告诉Entity Framework它不应该清除我的TemplateVersion关系?

Additional info: once I define my TemplateVersion entity as follows 附加信息:一旦我定义了我的TemplateVersion实体,如下所示

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

it's get even more interesting: previous instance of TemplateVersion is just deleted! 它变得更有趣:之前的TemplateVersion实例刚被删除!

Template ---- TemplateVersionCurrent.Template == Template

EF default conventions don't play well with multiple relationships between 2 entities. EF默认约定不适用于2个实体之间的多个关系。 And data annotations don't play well with one-to-one relationships or unidirectional associations (relationships without navigation property at one of the ends). 并且数据注释不能很好地与一对一关系或单向关联(在一端没有导航属性的关系)。

You need to explicitly configure the desired relationships with fluent API. 您需要使用流畅的API显式配置所需的关系。 Since fluent API have different overloads for having/not having navigation property and it's important to use to correct overload, let say your model is exactly like this (by exactly I mean the navigation and explicit FK properties which affect the relationships, other properties are irrelevant): 由于流畅的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; }
}

the fluent configuration of the desired two relationships is as follows: 所需两种关系的流畅配置如下:

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

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

Note that you have defined circular relationship, hence one of them should be optional. 请注意,您已定义了循环关系,因此其中一个应该是可选的。 I've choosen Template..TemplateVersionId to be the optional wich sounds logical to me. 我选择了Template..TemplateVersionId作为我认为合乎逻辑的选择。

Also note that for one-to-one relationships, the principal and dependent ends cannot be uniquely determined from HasOne / WithOne , so you need to use HasForeignKey and HasPrinciplaKey generic type argument to specify that (in contrast, one-to-many relationships have no such issue because the one side is always the principal and manu side is the dependent). 另请注意,对于一对一关系,主要和从属端不能从HasOne / WithOne唯一确定,因此您需要使用HasForeignKeyHasPrinciplaKey 泛型类型参数来指定(相反,一对多关系具有没有这样的问题,因为一方总是主要的,而manu方面是依赖的)。

For more info, see Relationships . 有关详细信息,请参阅关系

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM