【问题标题】:Entity Framework - Composite Primary Key formed by 3 Foreign Keys实体框架 - 由 3 个外键组成的复合主键
【发布时间】:2016-06-08 08:19:10
【问题描述】:

我正在创建 4 个表之间的关系:Provider、CostumerSite、DrmType 和 Drm。

关系:

在 Drm 表中有一个由其他 3 个表的主键组成的复合键。这是代码:

public partial class Provider
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ProviderId { get; set; }

    [StringLength(128)]
    [Required]
    public string Title { get; set; }

    // one-to-many
    public virtual ICollection<Content> Contents { get; set; }

    public virtual Drm Drm { get; set; }

}

 public partial class CustomerSite
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CustomerSiteId { get; set; }

    [Required]
    [StringLength(128)]
    public string Name { get; set; }

    [Required]
    [StringLength(128)]
    public string Username { get; set; }

    [Required]
    [StringLength(128)]
    public string Password { get; set; }

    // many-to-many
    public virtual ICollection<Content> Contents { get; set; }

    // one-to-one
    public virtual Drm Drm { get; set; }
}

 public partial class DrmType
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int DrmTypeId { get; set; }

    [Required]
    [StringLength(128)]
    public string Name { get; set; }

    // one-to-one
    public virtual Drm Drm { get; set; }
}

public partial class Drm
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int DrmId { get; set; }

    // one-to-one relation
    [Key, Column(Order = 1), ForeignKey("CustomerSite")]
    public int CustomerSiteId { get; set; }

    // one-to-one relation
    [Key,  Column(Order = 2), ForeignKey("Provider")]
    public int ProviderId { get; set; }

    // one-to-one relation
    [Key,  Column(Order = 3), ForeignKey("DrmType")]
    public int DrmTypeId { get; set; }

    public virtual Provider Provider { get; set; }
    public virtual CustomerSite CustomerSite { get; set; }
    public virtual DrmType DrmType { get; set; }
}

这是正确的吗?在此之后,我正在使用 onModel 函数:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<Drm>()
        .HasKey(d => new { d.ProviderId, d.CustomerSiteId, d.DrmType });

    }

但是以这种方式,当我启动“Enable-Migrations -EnableAutomaticMigrations -Force”命令时,它会显示错误:

在模型生成过程中检测到一个或多个验证错误:

Drm_CustomerSite_Source: : 多重性在角色中无效 关系“Drm_CustomerSite”中的“Drm_CustomerSite_Source”。因为 Dependent Role 属性不是关键属性,上 从属角色的多重性的界限必须是“”。 Drm_Provider_Source: : 多重性在角色中无效 关系“Drm_Provider”中的“Drm_Provider_Source”。因为 Dependent Role 属性不是关键属性,上限 从属角色的多重性必须是''。

你能解释一下如何解决这个问题吗?谢谢

【问题讨论】:

  • 现实中没有1:1关系,一直是0-1:1,关系的一侧必须是可选的。

标签: c# sql-server entity-framework code-first entity-framework-migrations


【解决方案1】:

根据您的模型,Drm 不应有自己的“id”。所以,它应该是这样的:

public partial class Drm
{
    //remove this property
    //[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    //public int DrmId { get; set; }

    // one-to-one relation
    [Key, Column(Order = 1), ForeignKey("CustomerSite")]
    public int CustomerSiteId { get; set; }

    // one-to-one relation
    [Key,  Column(Order = 2), ForeignKey("Provider")]
    public int ProviderId { get; set; }

    // one-to-one relation
    [Key,  Column(Order = 3), ForeignKey("DrmType")]
    public int DrmTypeId { get; set; }

    public virtual Provider Provider { get; set; }
    public virtual CustomerSite CustomerSite { get; set; }
    public virtual DrmType DrmType { get; set; }
}

由于您在类声明中提供了[Key] 属性,因此您无需在模型绑定中声明HasKey。所以,删除这一行:

modelBuilder.Entity<Drm>()
    .HasKey(d => new { d.ProviderId, d.CustomerSiteId, d.DrmType });

编辑

ProviderCustomerSiteDrmType 必须具有 Drm 的集合。

public partial class Provider
{
    //...
    //public virtual Drm Drm { get; set; }
    public virtual ICollection<Drm> Drms { get; set; }
}

public partial class CustomerSite
{
    //...
    //public virtual Drm Drm { get; set; }
    public virtual ICollection<Drm> Drms { get; set; }
}

public partial class DrmType
{
    //public virtual Drm Drm { get; set; }        
    public virtual ICollection<Drm> Drms { get; set; }
}

希望这会有所帮助!

【讨论】:

  • 但是这个解决方案是一对一的关系......在我的项目中,我创建了一个一对一的关系......
  • 您的图片显示了一对一的关系。 Drm PK 由 3 个 FK 组成。因此,它不能是 1 对 1。实现 1-1 的唯一方法是两个表共享相同的主键,这不是你的情况。 Drm 的 PK 不同于所有其他实体。有关更多说明,请参阅此链接entityframeworktutorial.net/code-first/…
【解决方案2】:

解决此问题的最简单方法是为 DRM 表提供自己的 ID,并使 3 个字段成为外键。 我不知道你规范化到什么程度,但这是为了防止不必要的复杂代码而经常做的事情。 保持干净,保持简单

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-20
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    相关资源
    最近更新 更多