1

我已经继承了一个遗留SQL数据库,我试图将其反向工程化为Code First。由于在当前配置上运行的传统软件,更改架构不是一个选项。对我来说奇怪的是,开发人员配置子表的复合主键由一个ChildId + ParentId组成,而不仅仅是ParentId。使用复合键的Code First Entity Framework 6:1到1

以下是我有:

public class Parent 
{ 

    public decimal PkParentId { get; set; } 
    public string ParentName { get; set; } 
    ... 
    public Child Child { get; set; } 
} 


public class Child 
{ 

    public decimal PkChildId { get; set; } 
    public decimal PkParentId { get; set; } 
    public string ChildName { get; set; } 
    ... 
    public Parent Parent { get; set; } 
} 

这里是我的映射。当我反向设计它时,EF想要在父母中创建一对一的孩子集合,但我真的想要1到0或1(一个孩子可能存在也可能不存在,但父母必须)。

public class ParentConfiguration : EntityTypeConfiguration<Parent> 
{ 
    public ParentConfiguration() 
    { 
     HasKey(p => p.PkParentId); 
     Property(p => p.PkParentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     HasOptional(p => p.Child).WithRequired(p => p.Parent); 

     // Also tried this 
     // HasOptional(p => p.Child).WithRequired(p => p.Parent).Map(p => p.MapKey("PkParentId")); 
    } 
} 

public class ChildConfiguration : EntityTypeConfiguration<Child> 
{ 
    public ChildConfiguration() 
    { 
     // Pk is composite on child 
     HasKey(e => new {e.PkChildId, e.PkParentId}); 
     Property(p => p.PkChildId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
    } 
} 

我一起取父子没有问题,但如果我尝试插入一个家长和孩子:

 var newParent = new Parent 
     { 
      ParentName = "XXX", 
      Child = new Child { ChildName = "YYY" } 
     }; 
     _dbContext.Parents.Add(newParent); 
     _dbContext.SaveChanges(); 

这将导致以下错误:指定的列名“PkParentId”更多比SET子句中的一次。在同一个SET子句中,列不能分配多个值。修改SET子句以确保列只更新一次。如果SET子句更新视图的列,那么列名'PkParentId'可能在视图定义中出现两次。

果然,如果检查生成的SQL,它试图插入两次PkParentId插入子插入,一次作为第一个参数,一次作为最后一次。这就像EF没有放在一起,PkParentId是外键父导航属性,所以我试图将此添加到子配置:

HasRequired(x => x.Parent).WithOptional(y => y.Child).Map(z => z.MapKey("PkParentId")); 

这会产生相同的错误。奇怪的是,我找不到一个可选的关系,它会让我使用除HasMore()之外的“HasForeignKey”强制我回到1:M。

回答

1

EF中的一对一始终包含一个也是外键的主键。孩子的主键复制父母的值并通过FK约束引用他们。

但孩子的主要关键与父母的主键完全一致!而事实并非如此。

但是这只是你知道的。 EF不必知道Child有一个组合键。只需通过标记PkChildId作为计算欺骗EF一点:

public ChildConfiguration() 
{ 
    // Pk is composite on child 
    HasKey(e => e.PkParentId); 
    Property(p => p.PkChildId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); 
} 

现在EF将能够识别Parent S和Child通过PkParentId仁只有当一个Child插入它只会从数据库中读取PkChildId,但不用它作为实体键。

+0

谢谢,工作很好。无法告诉你在此之前我尝试了多少个排列组合。 –

相关问题