【问题标题】:EntityFramework - Composite Key Table with FK to another Composite Key TableEntityFramework - 具有 FK 到另一个复合键表的复合键表
【发布时间】:2015-04-10 19:13:55
【问题描述】:

我有两个表,都具有复合主键两者在另一个表中具有共同的一个主键和一个外键

问题是当我创建迁移时,它会弄乱外键。

我必须使用数据注释。

例子:

public class City
{
    [Key, Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string CityCode { get; set; } 

    [Key, Column(Order = 2)]
    public string CompanyCode { get; set; }

    public string Description { get; set; }     

    [ForeignKey("CompanyCode")]
    public virtual Company Company { get; set; }
}

public class PostCode
{
    [Key, Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Code { get; set; } 

    [Key, Column(Order = 1)]
    public string CompanyCode { get; set; }

    public string Description { get; set; } 

    public string CityCode { get; set; }      

    [ForeignKey("CompanyCode")]
    public virtual Company Company { get; set; }

    [ForeignKey("CityCode, CompanyCode")]
    public virtual City City { get; set; }
}
  • PostCodeCity 有一个复合主键(代码,CompanyCode)。
  • PostCode 具有表 City 的外键(CityCodeCompanyCode)。

问题在于 CompanyCode主键的一部分,同时也是 City 的复合外键的一部分.

当我说它弄乱了外键时,我的意思是:

CONSTRAINT [FK_dbo.PostCodes_dbo.Companies_CompanyCode] FOREIGN KEY ([CompanyCode]) REFERENCES [dbo].[Companies] ([CompanyCode]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.PostCodes_dbo.Cities_CompanyCode_CityCode] FOREIGN KEY ([CompanyCode], [CityCode]) REFERENCES [dbo].[Cities] ([CityCode], [CompanyCode])

在第二个约束中,它用 CityCode 引用 CompanyCode,用 CompanyCode 引用 CityCode

我在互联网上找不到任何这样的例子。

我哪里错了?

提前致谢。

编辑 1

CityCompany 之间有一个简单的主键 CompanyCodePostCodesCompany 也是如此。

【问题讨论】:

  • 你能简单分享一下你的逻辑吗? CityCompany之间存在什么样的关系?
  • @octavioccl 好的,在Edit 1中写过,请再看一遍。

标签: entity-framework asp.net-mvc-5 entity-framework-6 foreign-key-relationship composite-primary-key


【解决方案1】:

如果您想在CityCompany 之间建立一对一的关系,恐怕按照您的模型是不可能的。在配置一对一关系时,Entity Framework 要求依赖端的主键也是外键,否则 EF 不会将其视为一对一关系。你的情况下的依赖端是City,但是你有一个问题,你想添加另一个PK,即CityCode,这打破了一对一的关系,因为例如,下面的记录可能会发生:

Company             City 
Id            CityCode CompanyId
1               ee33a      1
2               aa23b      1

这样,如果你想实现你的场景,我想你必须在CompanyCity之间建立一个一对多的关系。可以这样使用数据注释:

public class City
{
    [Key, Column(Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string CityCode { get; set; }

    [Key, ForeignKey("Company"),Column(Order = 2)]
    public string CompanyCode { get; set; }

    public string Description { get; set; }

    public virtual Company Company { get; set; }
}

public class Company
{
    public string Id { get; set; }
    public virtual ICollection<City> Cities { get; set; }
}

如果您不想引用与Company 相关的城市,可以省略Company 中的Cities 导航属性。

这同样适用于PostCode 实体。

更新:

要在 PostCode 实体中实现您想要的,您必须以这种方式映射 FK:

public class PostCode
{
    [Key, Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Code { get; set; }

    [Key,ForeignKey("City"), Column(Order = 2)]
    public string CityCompanyCode { get; set; }

    public string Description { get; set; }

    [ForeignKey("City"), Column(Order = 1)]
    public string CityCode { get; set; }


    public virtual City City { get; set; }

    [ForeignKey("Company")]
    public string CompanyCode { get; set; }
    public virtual Company Company { get; set; }
}

Here 是一个很好的例子,说明您应该如何处理复合 FK

【讨论】:

  • 感谢您的宝贵时间。但问题出在城市和邮政编码之间,因为我无法指定“城市”中的哪个主键与“邮政编码”中的外键匹配。我可以在 SQL 中模拟所有这些并让它工作,问题是实体框架弄乱了“PostCode”中的外键。如果您仔细查看我发布的 SQL 部分,您会看到外键 [dbo.PostCodes].CityCode 匹配 [dbo.Cities].CompanyCode 而不是 [dbo.Cities].CityCode。
  • 你好 Leandro,我已经更新了我的答案。您不能在一个属性中映射两个 FK(尽管它们代表相同的字段)。你必须把它们分开。希望对你有帮助
  • 但是我可以正常映射两个 FK(到一个复合主键表),这个问题只发生在我尝试从另一个复合主键表中进行映射时
  • 我知道,错误的 FK 映射是这样的:[ForeignKey("CityCode, CompanyCode")]。在 ForeignKey Attribute 中只指定了一个属性。您是否尝试过我在更新中向您推荐的变体?
  • 是的,它有效,但目标是只使用一个公司专栏
【解决方案2】:

我总是在我的表中添加一个主键,例如:CityId int、PostCode int。用这个我解决关系。

public class PostCode
{   
[Key, Column(Order = 0)]
public string PostCodeId  { get; set; } 

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Code { get; set; } 

public string CompanyCode { get; set; }

public string Description { get; set; } 

public string CityCode { get; set; }      

[ForeignKey("CompanyCode")]
public virtual Company Company { get; set; }

[ForeignKey("CityCode, CompanyCode")]
public virtual City City { get; set; }
}

谢谢

【讨论】:

  • 是的,我同意这会更容易,但现在这不是一个选择......谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 2018-07-11
相关资源
最近更新 更多