Entity Framework 4.1 Code First,一对一,一个表连接到复合键的单个键字段

Posted

技术标签:

【中文标题】Entity Framework 4.1 Code First,一对一,一个表连接到复合键的单个键字段【英文标题】:Entity Framework 4.1 Code First, One-to-One with one table joining to a single key field of of composite key 【发布时间】:2011-07-22 12:39:23 【问题描述】:

我刚刚开始使用 EF4.1 Code First,我非常喜欢它。

故事是这样的: Codif 类由来自 Domaine 类、Entite 类和 Reference 类的键和第四个字段组成,该字段是一些文本。 Reference 和 Codif 是一对一的关系。

事情是,当它创建数据库时,它会在我的参考实体中创建一些丑陋的字段,创建 Codif 实体的重复字段。 好点:但是,当我操作我的 Reference 对象时,我有访问 Codif 属性的预期行为,并且重复的字段是不可见的。

代码如下:

public class Reference

    public int ReferenceId  get; set; 
    public string Libelle  get; set; 
    public virtual Codif Codif  get; set; 



public class Domaine

    public int DomaineId  get; set; 
    public string Libelle  get; set; 



public class Codif

    [Key, Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int DomaineId  get; set; 
    [InverseProperty("DomaineId")]
    public virtual Domaine Domaine  get; set; 

    [Key, Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EntiteId  get; set; 
    [InverseProperty("EntiteId")]
    public virtual Entite Entite  get; set; 

    [Key, Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ReferenceId  get; set; 
    [InverseProperty("ReferenceId")]
    public virtual Reference Reference  get; set; 

    [Key, Column(Order = 3)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Codification  get; set; 


public class Entite

    public int EntiteId  get; set; 
    public string Nom  get; set; 
    public string Email  get; set; 

这是表格中的结果(图片):

Codif

Reference

    在 Reference 类中,如何指定 ReferenceId 是用于 Codif 的 SINGLE 字段的外键? 如何去除 Reference 中的重复字段? 如何在保留导航属性的同时删除 Codif 表中的 Reference_ReferenceId ?

感谢您的支持。

马克

编辑:我正在使用 SQL Compact Edition 4 数据库

【问题讨论】:

【参考方案1】:

将所有[InverseProperty("xxx")] 属性替换为[ForeignKey("xxx")]。我认为这就是你真正想要的。 [InverseProperty] 指的是关系另一端的导航属性,它永远不能是标量属性。

编辑

除了 FK 属性外,您还可以在 Codif 类中的 Reference 属性上设置 [InverseProperty] 属性:

public class Codif

//...

    [Key, Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ReferenceId  get; set; 
    [ForeignKey("ReferenceId")]
    [InverseProperty("Codif")] // <-- refers to Codif property in Reference class
    public virtual Reference Reference  get; set; 

//...

但它认为这并不是真正必要的,因为 EF 应该按照约定检测 ReferenceCodif 之间的正确关系。 (我不确定一对一的关系。)

编辑

问题!

首先:据我所知,您必须在 Fluent API 中指定一对一的关系,因为 EF 无法确定什么是主体,什么是依赖:

modelBuilder.Entity<Reference>()
            .HasOptional(c => c.Codif)
            .WithRequired(c => c.Reference);

第二:EF 仍然会因为组合键或者ReferenceId 不是唯一的键而抱怨。如果ReferenceIdCodif 中的唯一键,它将起作用。

编辑

我正在尝试了解您想要实现的目标。显然,Codif 中的组合键应该确保四个字段值的任何组合只能存在一次。但这与 imo 的一对一关系冲突,例如这将是有效的表条目:

Table Codif:
DomaineId    EntiteId    ReferenceId    Codification
----------------------------------------------------
1            1           1              "A"
2            1           1              "A"
1            2           1              "A"
1            1           2              "A"
1            1           1              "B"
etc...

但如您所见:您可以有多个具有相同ReferenceId 的行,这意味着您不能与Reference 建立一对一的关系。这里有 4 个 Codif 实体,它们引用同一个 ID = 1 的 Reference 实体。

现在,我想,您希望建立一对一关系这一事实意味着存在一个额外的约束,以便Codif 表中的ReferenceId 只能出现一次。换句话说:上面示例中的第 2、3 和 5 行从业务角度来看是无效的(尽管从 DB 角度来看是有效的)。

如果是这种情况,我实际上会将ReferenceId 设为Codif 中的单个键,并从业务逻辑确保数据库中的其他值组合是唯一的(在插入新的@987654344 之前查询是否存在@)。在数据库方面,您可以在其他三个字段上创建唯一索引,以确保组合在数据库中始终是唯一的。 EF 无法在内部对此进行检查,因为尚不支持唯一约束。

【讨论】:

以上是关于Entity Framework 4.1 Code First,一对一,一个表连接到复合键的单个键字段的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 4.1Code First 连接到 Sql Server 2005

Entity Framework 4.1 Code First 关系中的更改通常不需要

Entity Framework 4.1 Code First - 插入非主键时自动递增字段

我应该如何在 MVC3 中使用 Code First Entity Framework (4.1) 声明外键关系?

virtual 关键字在 Entity Framework 4.1 POCO Code First 中可以产生啥影响?

Entity Framework 4.1 Code First,一对一,一个表连接到复合键的单个键字段