C# 实体框架与有时独立的类一对一
我有一个父类C# 实体框架与有时独立的类一对一,c#,entity-framework,entity-framework-6,one-to-one,C#,Entity Framework,Entity Framework 6,One To One,我有一个父类ComponentDesign: public class ComponentDesign { public string Name { get; set; } public virtual JobFile DesignFile { get; set; } public int? DesignFileId { get; set; } public Pdf PdfFile { get; set; } public int? PdfFileId
ComponentDesign
:
public class ComponentDesign
{
public string Name { get; set; }
public virtual JobFile DesignFile { get; set; }
public int? DesignFileId { get; set; }
public Pdf PdfFile { get; set; }
public int? PdfFileId { get; set; }
public JobFile SealedPdfFile { get; set; }
public int? SealedPdfFileId { get; set; }
public int Id { get; set; }
public int JobId { get; set; }
}
以及子类JobFile
(其中Pdf
为子类):
这些类使用实体框架存储在关系数据库中。我希望在关系的两侧都有导航属性,这样我可以随意说componentDesign.PdfFile
或jobFile.componentDesign
ComponentDesign
中JobFile
类型的每个属性都是可选的,JobFile将只属于一个ComponentDesign。但是
JobFile可以是独立的,不属于任何
ComponentDesign(因此
JobFile.ComponentDesign`将为空)
我正在努力解决如何使用Fluent API来配置这种关系。这是一对一。是否可以在关系的两侧都有导航属性?请记住,JobFile
可以是独立的(因此JobFile.ComponentDesign
并不总是相关的),因此有属于ComponentDesign
的JobFile
和不属于ComponentDesign的。我觉得自己最近的经历是:
modelBuilder.Entity<ComponentDesign>()
.HasOptional(componentDesign => componentDesign.DesignFile)
.WithRequired(jobFile => jobFile.ComponentDesign);
modelBuilder.Entity()
.has可选(componentDesign=>componentDesign.DesignFile)
.WithRequired(jobFile=>jobFile.ComponentDesign);
但在我看来,这似乎表明总是需要jobFile.ComponentDesign
,但事实并非如此。我很犹豫是否尝试它,因为它将产生一些实质性的迁移,所以我想先获得输入。在这种情况下,我的Fluent API配置应该是什么样的?这样我才能理解它们之间的关系:
组件设计
->作业文件
=可选
JobFile
->ComponentDesign
=可选
这是一种零或一对零或一([0/1]-[0/1])关系
这可以通过以下方式实现,使用fluent API中的.WithOptionalPrincipal
方法。在1-0关系中,很明显哪一端是主端;和1一样-∞ 关系∞-∞ 由于创建的隐藏表控制每个关系之间的关系,因此关系没有主端。对于0/1-0/1或1-1关系,这并不明显,因此您必须告诉数据库使用哪一端作为关系的主端。在许多其他事情中,主要负责启动和维护表之间的关系
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure ComponentDesign & JobFile entity
modelBuilder.Entity<ComponentDesign>()
// Mark JobFile property optional in ComponentDesign entity.
.HasOptional(cd => cd.DesignFile)
// Mark ComponentDesign property optional in JobFile entity.
.WithOptionalPrincipal(jf => jf.ComponentDesign);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//配置组件设计和作业文件实体
modelBuilder.Entity()
//在ComponentDesign实体中将JobFile属性标记为可选。
.has可选(cd=>cd.DesignFile)
//将JobFile实体中的ComponentDesign属性标记为可选。
.具有可选原则(jf=>jf.组件设计);
}
或者,您可以为每个实体创建一个EntityTypeConfiguration
类来分离关系(如果有很多需要排序)。虽然这确实分散了关系,但更具可伸缩性,因为一旦配置了上下文,就可以通过MEF注入这些配置类。只是一个未来发展的想法
如果从作业文件端配置关系,则应使用.WithOptionalDependent
,以正确设置导航,而不是使用.withoptionaldeprincipal
。这完全取决于您从哪一方配置关系。ComponentDesign
实体对JobFile
实体的依赖远大于JobFile
实体对ComponentDesign
实体的依赖;因此,应将其配置为主体
如上所述,复杂属性应该用virtual
关键字修饰。这个延迟加载属性,并且,当类被初始化时,它将初始值设置为null
将数据库克隆到一个测试服务器,解决这个问题,然后在生产模型上实现更改;这样在迁移数据库时就不会丢失数据。要在Entity Framework中在两个对象类或datatables之间创建关系,可以将虚拟字与类类型一起使用。我相信您可以找到解决问题的虚拟属性结果。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure ComponentDesign & JobFile entity
modelBuilder.Entity<ComponentDesign>()
// Mark JobFile property optional in ComponentDesign entity.
.HasOptional(cd => cd.DesignFile)
// Mark ComponentDesign property optional in JobFile entity.
.WithOptionalPrincipal(jf => jf.ComponentDesign);
}