Прямая и непрямая конфигурация «многие ко многим» с использованием EF Core 5 с использованием

У меня есть следующие объекты

public class Course
{
    public long Id { get; set; }
    public virtual ICollection<User> Users{ get; set; }
    public virtual ICollection<UserCourse> CourseUsers { get; set; }
}

public class User
{
    public long Id { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
    public virtual ICollection<UserCourse> UserCourses { get; set; }
}

public class UserCourse
{
    public long UserId { get; set; }
    public User User { get; set; }

    public long CourseId { get; set; }
    public Course Course { get; set; }

    public bool IsRequired { get; set; }
}

со следующими отображениями для

Отображение пользовательского курса:

        builder
            .HasOne(nav => nav.User)
            .WithMany(self => self.UserCourses)
            .HasForeignKey(fk => fk.UserId)
            .OnDelete(DeleteBehavior.Cascade);

        builder
            .HasOne(nav => nav.Course)
            .WithMany(self => self.CourseUsers)
            .HasForeignKey(fk => fk.CourseId)
            .OnDelete(DeleteBehavior.Cascade);

и сопоставление пользователей

        builder
            .HasMany(nav => nav.Courses)
            .WithMany(nav => nav.Users);

При попытке создать новую миграцию я не совсем понимаю, почему я это получаю.

Невозможно использовать таблицу «UserCourse» для типа сущности «UserCourse», поскольку она используется для типа сущности «UserCourse (Словарь‹строка, объект›)» и, возможно, других типов сущностей, но нет связывающей связи. Добавьте внешний ключ в «UserCourse» в свойствах первичного ключа и укажите на первичный ключ в другом объекте, тип которого сопоставлен с «UserCourse».

Я понимаю, в чем ошибка, но не знаю, как заставить сопоставление UserCourse использовать созданную таблицу соединений, созданную сопоставлением пользователя, или наоборот.

Кроме того, мне нужно прямое сопоставление для OData и косвенное сопоставление с использованием объекта соединения для выполнения операций с DbSet<UserCourse>.


person boris    schedule 02.04.2021    source источник
comment
Используйте правильное сопоставление: docs.microsoft.com/en-us/ef/core/modeling/   -  person Gert Arnold    schedule 05.04.2021
comment
@GertArnold, можешь подробнее объяснить? Я не уверен, как я могу использовать это. Суть вопроса в том, чтобы сохранить обе навигационные опоры и выставить joinTable как DbSet.   -  person boris    schedule 05.04.2021
comment
Что ж, эта часть документов как раз подходит для вашего случая, не так ли? См. раздел Создание пользовательского типа CLR.   -  person Gert Arnold    schedule 05.04.2021


Ответы (1)


Сущность public virtual ICollection<User> Users{ get; set; } в Course и сущность public virtual ICollection<Course> Courses { get; set; } в Users являются избыточными. Сущности должны выглядеть примерно так

public class Course
{
   public long Id { get; set; }
   public virtual ICollection<UserCourse> UserCourses { get; set; }
}

public class User
{
   public long Id { get; set; }
   public virtual ICollection<UserCourse> UserCourses { get; set; }
}

public class UserCourse
{
    public long UserId { get; set; }
    public User User { get; set; }

    public long CourseId { get; set; }
    public Course Course { get; set; }

}

И метод OnModelCreating должен иметь этот код

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<UserCourse>()
               .HasKey(uc => new { uc.UserId, uc.CourseId }); 

   modelBuilder.Entity<UserCourse>()
               .HasOne(uc => uc.Course)
               .WithMany(c => c.Users)
               .HasForeignKey(uc => uc.CourseId); 

   modelBuilder.Entity<UserCourse>()
               .HasOne(uc => uc.User)
               .WithMany(c => c.Courses)
               .HasForeignKey(uc => uc.UserId);  

    }

Если вы используете EF core 5, вы можете напрямую пропустить таблицу соединений. Он будет сгенерирован и обработан EF за кулисами. Подробнее по этой теме здесь https://www.thereformedprogrammer.net/updating-many-to-many-relationships-in-ef-core-5-and-above/

person Anton Kovachev    schedule 02.04.2021
comment
как я уже сказал, я хочу сохранить обе ссылки - person boris; 03.04.2021
comment
Я не уверен, возможно ли это. И почему вы хотите сохранить и public virtual ICollection<User> Users{ get; set; }, и public virtual ICollection<UserCourse> CourseUsers { get; set; }, если вы можете получить доступ к Users из UserCourse? - person Anton Kovachev; 03.04.2021