#sql-server #entity-framework #.net-5
#sql-сервер #сущность-фреймворк #.net-5
Вопрос:
У меня есть 3-стороннее отношение «многие ко многим», подобное этому:
table 1 skill
table 2 instructions
table 3 person
Теперь мне нужно иметь способ задать для комбинации навыков и person список инструкций. Я думал о том, чтобы иметь 1 таблицу с этим отображением SkillId, InstructionId и PersonID. Я попытался настроить его с помощью hasOne.Со многими.Имеет ForeignKey, но он не работает. Я получаю сообщение об ошибке
Свойство или навигационная ‘Инструкция’ не может быть добавлена к объекту типа ‘PersonSkillInstruction’, поскольку свойство или навигация с тем же именем уже существуют для объекта типа ‘PersonSkillInstruction’
Если я настрою только первичные ключи и позволю .netcore 5.0 сделать это за меня, я получаю еще одну ошибку
Свойство ‘PersonSkillInstruction.Инструкция’ имеет тип ‘InstructionEntity’, который не поддерживается текущим поставщиком базы данных. Либо измените тип CLR свойства, либо игнорируйте свойство, используя атрибут ‘[NotMapped]’ или используя EntityTypeBuilder.Игнорировать ‘в ‘OnModelCreating’
Я знаю, что мог бы сделать что-то вроде создания «многие ко многим» для person и skill и установить идентификатор, а затем использовать его в сочетании с инструкцией, но это выглядит очень подозрительно.
Как я могу заставить этот 3-способ «многие ко многим» работать?
Я использую .netcore 5.0, ef core, code first и sqlserver
Ответ №1:
Я думаю, что правильно было бы сделать то, что ты сказал:
Я знаю, что мог бы сделать что-то вроде создания множества для многих для person и skill и установить идентификатор, а затем использовать его в сочетании с инструкцией
Тем не менее, здесь у вас есть пример, если вы хотите создать таблицу PersonSkillInstruction.
public class PersonSkillInstruction
{
[ForeignKey("person")]
public int PersonId { get; set; }
[ForeignKey("skill")]
public int SkillId { get; set; }
[ForeignKey("instructions")]
public int InstructionId { get; set; }
public virtual Person Person { get; set; }
public virtual Skill Skill { get; set; }
public virtual Instruction Instruction { get; set; }
}
Затем вам нужно установить PK в DbContext следующим образом:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// ...
modelBuilder.Entity<PersonSkillInstruction>()
.HasKey(t => new { t.PersonId, t.SkillId, t.InstructionId });
// ...
После добавления новой миграции вы должны ссылаться на два таких действия, чтобы избежать циклов:
// ...
onDelete: ReferentialAction.Restrict
// ...
Если в этой таблице будут выполняться тяжелые запросы, я предлагаю использовать суррогатный ключ с уникальным индексом, подобный этому:
modelBuilder.Entity<PersonSkillInstruction>()
.HasIndex(t => new { t.PersonId, t.SkillId, t.InstructionId })
.IsUnique();