使用 CodeFirst 的 C# 一对零或一关系

Posted

技术标签:

【中文标题】使用 CodeFirst 的 C# 一对零或一关系【英文标题】:C# One-To-Zero-Or-One relationship using CodeFirst 【发布时间】:2017-10-05 02:49:14 【问题描述】:

所以我有以下代码:

ParentModel.cs

public class ParentModel 
   public int ParentModelID get; set;
   ...other fields here

   public ChildModel ChildModel get; set;

ChildModel.cs

public class ChildModel
   [ForeignKey("ParentModel")]
   public int ChildModelID get; set;
   ...other fields and navigation properties here

   public int ParentModelID get; set;
   public ParentModel ParentModel get; set;

所以数据库生成成功。当我尝试保存数据时出现问题。例如,我首先将数据保存到ParentModel 并成功保存。但是当我保存在ChildModel 中时,即使我的数据包含ParentModel 的 id,它也会给我以下错误:

INSERT 语句与 FOREIGN KEY 约束“FK_dbo.ChildModels_dbo.ParentModels_ChildModelID”冲突。冲突发生在数据库“MyDatabaseName”、表“dbo.ParentModels”、列“ParentModelID”中。声明已终止。

【问题讨论】:

【参考方案1】:

在流畅的 api 中使用以下功能

public class ParentModel 

   public int ParentModelID get; set;
   ...other fields here
   public virtual ChildModel childModel get; set;




public class ChildModel
   public int ParentModelID get; set;
   public int ChildModelID get; set;
   ...other fields and navigation properties here


   public virtual ParentModel parentModel get; set;

那我就用fluent api来建立关系

protected override void OnModelCreating(DbModelBuilder modelBuilder)

    // Configure ParentModelID as PK for ChildModel
    modelBuilder.Entity<ChildModel>()
        .HasKey(e => e.ParentModelID);

    // Configure ParentModelID as FK for ChildModel
    modelBuilder.Entity<ParentModel>()
                .HasOptional(s => s.childModel) 
                .WithRequired(ad => ad.ParentModelID); 


【讨论】:

当我按照你的回答我得到以下错误:One or more validation errors were detected during model generation: ChildModel_ParentModel_Source: : Multiplicity is not valid in Role 'ChildModel_ParentModel_Source' in relationship 'ChildModel_ParentModel'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'. 您是否将 [Key] 字段添加到主键? 是的,我做到了。我刚刚复制了你的答案。 您是否对 parentModel 进行了更改? 不,我不能那样做,因为我需要的是一对一或一对零的关系。【参考方案2】:

你几乎拥有它;您想要一个已设置的共享主键。问题是您可能正在使用父 ID 设置 ChildModel.ParentModelID 属性。删除该属性并将ChildModel.ChildModelID 设置为Parent 实体的ParentModelID - ChildModelIDParentModel 实体的FK。您还需要将ChildModel.ParentModel 设为必需。

public class ParentModel 

   public int ParentModelID get; set;
   public ChildModel ChildModel get; set;


public class ChildModel

   [ForeignKey("ParentModel")]
   public int ChildModelID get; set;
   [Required]
   public ParentModel ParentModel get; set;


var parent = new ParentModel();
dbContext.Set<ParentModel>().Add( parent );
dbContext.SaveChanges();

var child = new ChildModel()

     ChildModelID = parent.ParentModelID
;
dbContext.Set<ChildModel>().Add( child );
dbContext.SaveChanges();

另一个例子见this answer。

【讨论】:

以上是关于使用 CodeFirst 的 C# 一对零或一关系的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 中实现一对零或一关系

用于一对零或一关系的实体框架 (EF) 代码优先级联删除

EF 代码优先 - 配置一对零或一关系,无需共享 PK/FK

实体代码第一个零或一到零或一关系

一对多和多对一关系的区别

SQLAlchemy学习-9.一对多和多对一关系