I have Entity Framework Core which performs additional delete which I don't want.
Model definition: I have two entities Template
and TemplateVersion
. A TemplateVersion
are just next versions of template, so TemplateVersion
has one Template
(N:1 relation)
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)
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
And here the magic starts: when I add one Template
and one TemplateVersion
all is working good.
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 ---- 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.
How can I tell Entity Framework that it should not clear my TemplateVersion
relation?
Additional info: once I define my TemplateVersion
entity as follows
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!
Template ---- TemplateVersionCurrent.Template == Template
EF default conventions don't play well with multiple relationships between 2 entities. 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. 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):
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.
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).
For more info, see Relationships .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.