我正在将应用程序转换为Entity Framework Core,并且在我的两个模型类之间获取外键关系时遇到了麻烦。类是这样设置的(注意在---
title: "test"
author: "Stéphane Laurent"
date: "30 mars 2018"
output:
pdf_document:
includes:
in_header: header.tex
---
上声明了Guid Id
字段):
BaseEntity
关系背后的想法是,一个public class Crt : BaseEntity
{
[Required]
public Guid FacId { get; set; }
[Required]
public string Code { get; set; }
[ForeignKey("ActiveCrtChk")
public Guid? ActiveCrtChkId { get; set; }
public string Description { get; set; }
public string Device { get; set; }
#region navigation properties
public CrtChk ActiveCrtChk;
public List<CrtChk> CartChecks;
#endregion
}
public class CrtChk : BaseEntity
{
[Required]
public Guid CrtId { get; set; }
[Required]
public string Device { get; set; }
[Required]
public Guid OutSysUsrId { get; set; }
[Required]
public DateTime OutSysDateTime { get; set; }
public Guid? InSysUsrId { get; set; }
public DateTime? InSysDateTime { get; set; }
[Required]
public string Type { get; set; }
#region navigation properties
public Crt Cart { get; set; }
public Usr OutSysUsr { get; set; }
public Usr InSysUsr { get; set; }
public List<CrtEvt> CartEvents { get; set; }
#endregion
}
可以包含多个Crt
条记录,但CrtChk
也会存储活动的Crt
Id
记录。
当我运行迁移时,它会生成CrtChk
和Crt
之间所期望的所有外键关系,除了没有为CrtChk
字段生成外键。
通过阅读this post我的理解是ActiveCrtChkId
属性ForeignKey
属性的ActiveCrtChkId
导航属性的名称,我应该得到一个外国人我的迁移中的关键约束。
我在这里缺少什么?
修改
在修正了将ActiveCrtChk
导航属性声明为字段的错误后,我在尝试创建迁移时偶然发现了一个新错误。
Crt
我认为Unable to determine the relationship represented by navigation property 'Crt.ActiveCrtChk' of type 'CrtChk'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
属性是手动配置关系的吗?我是否需要使用Fluent API来创建关系?如果是这样,我如何使用Fluent API建立一对一(ForeignKey
到Crt
)和一对多(与ActiveCrtChk
关联的所有CrtChks的关系)?
答案 0 :(得分:2)
这是可能的,但由于这种设计会在两个实体之间产生循环依赖,因此会导致很多问题。例如,不仅一个关系(假设从return "production code that should operate with different variations of $amounte and $redeem on last iteration";
到CrtChk
)不能使用级联删除,而且您不能在不首先更新{{1}的情况下删除Crt
} Crt
(并调用ActiveCrtChkId
)。
无论如何,这是您配置所需关系的方式。通常使用null
属性来解决导航属性映射歧义就足够了,但是一对一的单向(即仅在一端具有导航属性)需要流畅的配置(否则它将按惯例映射)一对多)。还特别针对关系,我发现明确的流畅配置比考虑所有EF常规假设和数据注释更明确,比如放置SaveChanges
属性(在FK属性或导航属性上),放在那里的第一个或更晚的字符串案例等。
不久,以下是相关关系的完整显式配置:
InverseProperty
请注意,ForeignKey
属性不能在两种关系中使用。首先,因为每个导航属性只能映射到一个关系。其次,因为关系模型不能强制// Crt 1 - 0..N CrtChk
modelBuilder.Entity<Crt>()
.HasMany(e => e.CartChecks)
.WithOne(e => e.Cart)
.HasForeignKey(e => e.CrtId)
.OnDelete(DeleteBehavior.Cascade);
// CrtChk 1 - 0..1 Crt
modelBuilder.Entity<Crt>()
.HasOne(e => e.ActiveCrtChk)
.WithOne()
.HasForeignKey<Crt>(e => e.ActiveCrtChkId)
.OnDelete(DeleteBehavior.Restrict);
FK引用的Cart
记录与引用它的CrtChk
的{{1}}具有相同的ActiveCrtChkId
- 它可以任何其他(虽然逻辑上意图不同)。