Entity Framework с ошибкой составного ключа внешних ключей - PullRequest
1 голос
/ 15 марта 2019

Я немного новичок в Entity Framework. У меня есть класс, определенный следующим образом, соответствующий таблице базы данных с составным внешним ключом, состоящим из двух столбцов: GroupID и CompanyID, а также третьего внешнего ключа с именем 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; }
}

Я попытался следующий запрос, чтобы получить MemberCode, когда у меня есть значения для GroupID и MemberCompanyID:

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

Я получаю следующее исключение:

Свойство 'GroupID' нельзя настроить как свойство навигации. Свойство должно иметь допустимый тип сущности, а свойство должно иметь неабстрактный метод получения и установки. Для свойств коллекции тип должен реализовывать ICollection, где T является допустимым типом сущности

Я думаю, что я что-то упускаю в методе OnModelCreating, я попробовал следующее, но это не сработало:

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

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

Следует также отметить, что оба GroupID и MemberID оба ссылаются на один и тот же столбец первичного ключа, который называется OrganizationID в таблице с именем Organizations, просто разные значения. Я не уверен, влияет ли это на что-нибудь.

Кто-нибудь может указать мне правильное направление? Спасибо!

1 Ответ

1 голос
/ 15 марта 2019

Этот код немного сбивает с толку, и я не совсем уверен, как он скомпилирован.:) Я думаю, что вы будете искать что-то более похожее на:

[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 свяжет их так, чтобы вы могли загрузить их данные и ссылаться на них через этиproperties.

Ленивая загрузка: (осторожно, так как это может означать дополнительные запросы к БД)

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

Выбрать можно использовать для заполнения чего-то вроде ViewModel или DTO, что является очень мощным вариантом использования EF без риска отключения вызовов отложенной загрузки.Преимущество этого подхода состоит в том, что запрос, отправляемый в БД, просто возвращает поля, необходимые для заполнения данных, а не все из сущности и связанных свойств навигации.

...