实体框架4.1代码优先,一对一,一个表连接到复合键的单个键字段

时间:2011-07-22 12:39:24

标签: entity-framework-4.1 ef-code-first

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

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

事情是,当它创建数据库时,它会在我的Reference实体中创建一些丑陋的字段,从而创建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

  1. 在Reference类中,如何指定ReferenceId是用于对抗Codif的SINGLE字段的外键?
  2. 如何摆脱参考文献中的那些重复字段?
  3. 如何在保留导航属性的同时删除Codif表中的Reference_ReferenceId?
  4. 感谢您的支持。

    马克

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

1 个答案:

答案 0 :(得分:0)

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

修改

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

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);

第二:由于组合密钥或因ReferenceId不是单独的密钥,EF仍然会抱怨。如果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实体。

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

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