Entity Framework Core 2, связывающий многие со многими

Это моя модель, и между программой обучения и учебным модулем установлены отношения «многие ко многим». Следующее, что я не уверен, что это наилучшая практика, — это выпуск табличного обучения. Для этого требуется соединение «1 ко многим» с этим «многим ко многим» LearningProgrammeAssignment. Нужно ли создавать идентификатор в LearningProgrammeAssignment? Или я могу просто сослаться на него в LearningRelease?

public class MyContext : DbContext
{
    public DbSet<LearningProgramme> LearningProgrammes { get; set; }
    public DbSet<LearningModule> LearningModules { get; set; }
    public DbSet<LearningProgrammeAssignment> LearningProgrammeAssignments { get; set; }
    public DbSet<LearningRelease> LearningReleases { get; set; }

}

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<LearningProgrammeAssignment>()
            .HasKey(p => new { p.LearningModuleId, p.LearningProgrammeId });
    }

public class LearningProgramme
{
 public int LearningProgrammeId { get; set; }
 public string LearningProgrammeTitle { get; set; }
 public List<LearningProgrammeAssignment> LearningProgrammeAssignments { get; set; }
}

public class LearningModule
{
  public int LearningModuleId { get; set; }
  public string LearningModuleTitle { get; set; }
 public List<LearningProgrammeAssignment> LearningProgrammeAssignments { get; set; }
}

public class LearningProgrammeAssignment
{
    public int LearningProgrammeId { get; set; }
    public int LearningModuleId { get; set; }
    public LearningProgramme LearningProgramme { get; set; }
    public LearningModule LearningModule { get; set; }
}

public class LearningRelease
{
 public int LearningReleaseId { get; set; }
 public int systemcode { get; set; }
 public DateTime ReleaseDate { get; set; }   
     //add in the LearningProgrammeAssignment id 
}

Похоже, LearningProgrammeAssignment — это не просто таблица присоединения. Возможно, вам лучше добавить свой собственный первичный ключ, как вы думали. Затем вы можете связать это с LearningRelease как с обычной сущностью.

Jan Paolo Go 12.03.2019 15:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вам нужна связь «один ко многим» между LearningRelease и LearningProgrammeAssignment, вам нужно определить LearningReleaseId внутри LearningProgrammeAssignment в качестве внешнего ключа, чтобы правильно настроить связь:

namespace DL.SO.EFCore.Learning.Data.Entities
{
    public class LearningProgrammeAssignment
    {
        public int LearningProgrammeId { get; set; }
        public LearningProgramme LearningProgramme { get; set; }

        public int LearningModuleId { get; set; }
        public LearningModule LearningModule { get; set; }

        public int LearningReleaseId { get; set; }
        // Optional
        public LearningRelease LearningRelease { get; set; }
    }
}

Свойство навигации LearningRelease является необязательным. Это зависит от того, хотите вы этого или нет. То же самое для отношения «многие» внутри LearningRelease:

using System;
using System.Collections.Generic;

namespace DL.SO.EFCore.Learning.Data.Entities
{
    public class LearningRelease
    {
        public int LearningReleaseId { get; set; }
        public int SystemCode { get; set; }
        public DateTime ReleaseDate { get; set; }

        public List<LearningProgrammeAssignment> LearningProgrammeAssignments { get; set; }
    }
}

Затем вам просто нужно настроить их обычным способом:

using DL.SO.EFCore.Learning.Data.Configurations;
using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;

namespace DL.SO.EFCore.Learning.Data
{
    public class LearningDbContext : DbContext
    {
        public LearningDbContext(DbContextOptions<LearningDbContext> options) : base(options) { }

        public DbSet<LearningModule> LearningModules { get; set; }
        public DbSet<LearningProgramme> LearningProgrammes { get; set; }
        public DbSet<LearningProgrammeAssignment> LearningProgrammeAssignments { get; set; }
        public DbSet<LearningRelease> LearningReleases { get; set; }

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

            modelBuilder.ApplyConfiguration(new LearningModuleConfiguration());
            modelBuilder.ApplyConfiguration(new LearningProgrammeConfiguration());
            modelBuilder.ApplyConfiguration(new LearningProgrammeAssignmentConfiguration());
            modelBuilder.ApplyConfiguration(new LearningReleaseConfiguration());
        }
    }
}

Ключ в LearningProgrammeAssignmentConfiguration (другие конфигурации для ясности не выложены):

using DL.SO.EFCore.Learning.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace DL.SO.EFCore.Learning.Data.Configurations
{
    public class LearningProgrammeAssignmentConfiguration : IEntityTypeConfiguration<LearningProgrammeAssignment>
    {
        public void Configure(EntityTypeBuilder<LearningProgrammeAssignment> builder)
        {
            // Composite key
            builder.HasKey(x => new { x.LearningModuleId, x.LearningProgrammeId });

            // Setup Many-To-Many relationship between LearningModule and LearningProgramme
            builder.HasOne(x => x.LearningModule)
                .WithMany(x => x.LearningProgrammeAssignments)
                .HasForeignKey(x => x.LearningModuleId);

            builder.HasOne(x => x.LearningProgramme)
                .WithMany(x => x.LearningProgrammeAssignments)
                .HasForeignKey(x => x.LearningProgrammeId);

            // Setup One-To-Many relationship between LearningRelease and LearningProgrammeAssignment
            builder.HasOne(x => x.LearningRelease)
                .WithMany(x => x.LearningProgrammeAssignments)
                .HasForeignKey(x => x.LearningReleaseId);

            // Alternately:
            //   you don't have to put the navigation property LearningRelease 
            //   in this LearningProgrammeAssignment, as you can setup 
            //   One-To-Many relationship without navigation properties like 
            //   this:
            //builder.HasOne<LearningRelease>()
            //    .WithMany()
            //    .HasForeignKey(x => x.LearningReleaseId);

            builder.ToTable("LearningProgrammeAssignment");
        }
    }
}

И результат:

Спасибо, Дэвид, прекрасное объяснение

W Morris 13.03.2019 12:27

Другие вопросы по теме