实体框架与外键错误的复合键

问题描述 投票:1回答:1

我对Entity Framework有点新鲜。我有一个类定义如下,对应于一个数据库表,其中一个复合外键由两列组成: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; }
}

当我有MemberCodeGroupID的值时,我尝试了以下查询来检索MemberCompanyID

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都指向相同的主键列,在名为OrganizationID的表中称为Organizations,只是不同的值。我不确定这是否会影响任何事情。

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

c# database entity-framework composite-primary-key
1个回答
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将连接这些实体,以便您可以加载其数据并通过这些属性引用它们。

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

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而不会有延迟加载调用的风险。这种方法的优点是发送给DB的查询只返回填充数据所需的字段,而不是实体和相关导航属性中的所有字段。

© www.soinside.com 2019 - 2024. All rights reserved.