EF Core, я должен добавить Id внешнего ключа в классе? - PullRequest
0 голосов
/ 13 марта 2020

Я читаю некоторые учебники с разных сайтов, некоторые добавляют Id внешнего ключа, а некоторые нет, а другие добавляют виртуальные.

Например:

class Class
{
    public int Id { get; set; }
    public string ClassName { get; set; }
    public List<Student> Students { get; set; }
}

class Student
{
    public int Id { get; set; }
    public string StudentName { get; set; }
    public Class class { get; set; }
}

Здесь, в Student класс, некоторые используют виртуальный на Class, а некоторые используют ClassId внутри Student класса.

Каков наилучший способ для этого? Я использую EF Core 3 с. NET Core 3.1 (последний)

Ответы [ 2 ]

2 голосов
/ 13 марта 2020

Шаблон называется " Свойство тени ". Допустим, мы хотим получить все Students с помощью ClassId.

с Shadow Property, двумя вариантами доступа к данным:

context.Classes.Include(x => x.Students).FirstOrDefault(x => x.Id == classId)?.Students;

//we have to know the name of foreign key from db.
context.Students.Where(x => EF.Property<int>(x, "ClassId") == classId).ToList(); 

С явным внешним ключом код :

context.Students.Where(x => x.ClassId == classId).ToList();

2-й и 3-й код позволяют избежать join, выглядит лучше. но какой из двух стилей лучше? это действительно зависит от проекта и предпочтений стиля кодирования.

хотя второй стиль прост в настройке:

class MyContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Class> Classes { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Add the shadow property to the model
        modelBuilder.Entity<Student>()
            .Property<int>("ClassId");

        // Use the shadow property as a foreign key
        modelBuilder.Entity<Student>()
            .HasOne(p => p.Class)
            .WithMany(b => b.Students)
            .HasForeignKey("ClassId");
    }
}

Вот 2 ссылки:

  1. https://docs.microsoft.com/en-us/ef/core/modeling/shadow-properties

  2. https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key

0 голосов
/ 13 марта 2020

В контексте EF пометка свойства как виртуального позволяет EF использовать отложенную загрузку для его загрузки. Чтобы ленивая загрузка работала, EF должен создать прокси-объект, который переопределяет ваши виртуальные свойства с помощью реализации, которая загружает указанную сущность при первом обращении к ней. Если вы не пометите свойство как виртуальное, то отложенная загрузка не будет работать с ним.

Для веб-приложений, возможно, лучше не использовать отложенную загрузку, потому что отложенная загрузка может тянуть огромное количество данных.

Предполагая, что вы хотите сгенерировать модель / отношения вашей базы данных из ваших объектов / классов (миграция кода вначале с ядром EF), наиболее важной частью являются конфигурации отображения ваших сущностей (либо с аннотациями). в свойствах вашей модели или с помощью Fluent API).

Если у вас нет особых требований c относительно формата свойства "Id", просто установите его для создания базой данных.

В вашем случае я бы настроил его следующим образом:

class Class
{
    public int ClassId { get; set; }
    public string ClassName { get; set; }
    public ICollection<Student> Students { get; set; }
}

class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public int ClassId { get; set; }
    public Class class { get; set; }
}

И один из способов настройки сопоставлений с помощью Fluent API может выглядеть примерно так:

public class StudentConfiguration : IEntityTypeConfiguration<Student>
{
    public void Configure(EntityTypeBuilder<Student> builder)
    {
        builder
             .HasKey(s => s.StudentId);

        builder
            .Property(s => s.StudentId)
            .UseIdentityColumn();

        builder
            .Property(c => c.StudentName)
            .HasMaxLength(<studentName_maxLength>);

        builder
            .HasOne(s => s.Class)
            .WithMany(c => c.Students)
            .HasForeignKey(s => s.ClassId);

        builder
            .ToTable("Student");
    }
}

public class ClassConfiguration : IEntityTypeConfiguration<Class>
{
    public void Configure(EntityTypeBuilder<Class> builder)
    {
        builder
             .HasKey(c => c.ClassId);

        builder
            .Property(c => c.ClassId)
            .UseIdentityColumn();   

        builder
            .Property(c => c.ClassName)
            .HasMaxLength(<className_maxLength>);

        builder
            .HasMany(c => c.Students)
            .WithOne(s => s.Class);

        builder
            .ToTable("Class");
    }
}

Подробнее подробную информацию о настройке сопоставлений «один-ко-многим» в Fluent API можно найти здесь

...