【问题标题】:Entity Framework with composite key of foreign keys error具有外键组合键的实体框架错误
【发布时间】:2019-03-14 21:51:07
【问题描述】:

我对实体框架有点陌生。我有一个定义如下的类,对应于一个数据库表,该表具有由两列组成的复合外键:GroupIDCompanyID,以及名为 RegionID 的第三个外键:

[Table("GroupMembers")]
public class GroupMember
{
    [Key, ForeignKey("GroupID"), Column(Order = 1)]
    public int GroupCompanyID { get; set; }

    [Key, ForeignKey("CompanyID"), Column(Order = 2)]
    public int MemberCompanyID { get; set; }

    [Column("MemberCode")]
    public string MemberCompanyCode { get; set; }

    [Column("RegionID")]
    public int RegionId { get; set; }
}

当我拥有GroupIDMemberCompanyID 的值时,我尝试了以下查询来检索MemberCode

var GroupMember = await repository.GroupMembers
                                  .FirstOrDefaultAsync(x => x.MemberID == memberId && 
                                                            x.CompanyID == manufacturerId);

我得到以下异常:

属性“GroupID”不能配置为导航属性。该属性必须是有效的实体类型,并且该属性应该具有非抽象的 getter 和 setter。对于集合属性,类型必须实现 ICollection,其中 T 是有效的实体类型

我认为我在 OnModelCreating 方法中遗漏了一些东西,我尝试了以下方法,但没有奏效:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<GroupMember>()
            .HasKey(gm => new {gm.GroupID, gm.MemberID});            
}

另外需要注意的是,GroupIDMemberID 都引用同一个主键列,在名为Organizations 的表中称为OrganizationID,只是值不同。我不确定这是否会影响任何事情。

谁能指出我正确的方向?谢谢!

【问题讨论】:

  • 什么是repository.CompanyGroupMembers
  • 对不起,这是我的错字,我对 GroupMembers 进行了调整。谢谢!

标签: c# database entity-framework composite-primary-key


【解决方案1】:

该代码有点混乱,我什至不确定它是如何编译的。 :) 我的想法是你会寻找更多类似的东西:

[Table("GroupMembers")]
public class GroupMember
{
    [Key, ForeignKey("Group"), Column(Order = 1)]
    public int GroupCompanyID { get; set; }

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

    [Column("MemberCode")]
    public string MemberCompanyCode { get; set; }

    [Column("RegionID")]
    public int RegionId { get; set; }

    public virtual Company Company { get; set; }
    public virtual Group Group { get; set; }
}

[Table("Companies")]
public class Company
{
    [Key]
    public int CompanyID { get; set; }
    public string Name { get; set; }
    // ...
}

[Table("Groups")]
public class Group
{
    [Key]
    public int GroupID { get; set; }
    // ...
}

导航属性指向相关实体,EF 会将它们连接起来,以便您可以加载它们的数据并通过这些属性引用它们。

延迟加载:(注意,这可能意味着对数据库运行额外的查询)

var groupMember = context.GroupMembers.FirstOrDefault(x => x.RegionId == 4);
var companyName = groupMember.Company.Name; // Context will check if the company is loaded and load it if needed.

渴望加载:

var groupMember = context.GroupMembers
    .Include(x => x.Company)
    .Include(x => x.Group)
    .FirstOrDefault(x => x.RegionId == 4);
var companyName = groupMember.Company.Name; // Member's company (and group) already loaded above.

选择地图:(匿名类型示例)

var groupMemberDetails = context.GroupMembers
    .Where(x=> x.RegionId == 4)
    .Select(x => new 
    { 
        x.GroupId,
        x.CompanyId,
        x.RegionId,
        CompanyName = x.Company.Name
    }).FirstOrDefault();

Select 可用于填充 ViewModel 或 DTO 之类的东西,这是一个非常强大的选项,可以利用 EF 而不会触发延迟加载调用。这种方法的优点是发送到数据库的查询只返回填充数据所需的字段,而不是来自实体和相关导航属性的所有内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2011-05-09
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    相关资源
    最近更新 更多