#c# #database #entity-framework #composite-primary-key
#c# #База данных #entity-framework #составной первичный ключ
Вопрос:
Я немного новичок в 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 amp;amp;
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. Что такое
repository.CompanyGroupMembers
?2. Извините, это была опечатка с моей стороны, я внес коррективы в GroupMembers. Спасибо!
Ответ №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.
Выберите Map: (пример анонимного типа)
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 без риска отключения вызовов отложенной загрузки. Преимущество этого подхода заключается в том, что запрос, отправляемый в базу данных, возвращает только поля, необходимые для заполнения данных, а не все из объекта и связанных с ним свойств навигации.