我什么时候需要在 EF 的 DbContext 中指定 DbSet?

Mar*_*all 5 .net c# asp.net entity-framework dbcontext

我有点困惑。直到今天,我认为每个表(由 EF 使用)都必须在DbContext类中指定。但看起来我需要一个!真的吗?

让我解释一下,这是我的 DbContext:

public class MyDbContext : DbContext
{
    public MyDbContext()
        : base("name=MyDbContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MyDbContext>(null);
        base.OnModelCreating(modelBuilder);
    }    

    public DbSet<Table1> Table1 { get; set; }
    public DbSet<Table2> Table2 { get; set; }
    public DbSet<Table3> Table3 { get; set; }
    public DbSet<Table4> Table4 { get; set; }
    public DbSet<Table5> Table5 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是两个示例表,连接 1:many

[Table("Table1")]
public class Table1
{
    [Key]
    [Column("Table1Id", TypeName = "uniqueidentifier")]
    public int Table1Id { get; set; }

    [Column("Table2Id", TypeName = "int")]
    public int Table2Id { get; set; }

    [ForeignKey("Table2Id")]
    public Table2 Table2 { get; set; }
}

[Table("Table2")]
public class Table2
{
    public Table2()
    {
        this.Table1s = new HashSet<Table1>();
    }

    [Key]
    [Column("Table2Id", TypeName = "int")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Table2Id { get; set; }

    public ICollection<Table1> Table1s { get; set; }
} 
Run Code Online (Sandbox Code Playgroud)

简单。现在,我想用相应的 Table1 查询所有 Table2。我愿意:

var tables2 = fni.Set<Table2>()
    .Include(i => i.Table1s)
    .Where(t => t.Table2Id == 123456).ToList();
Run Code Online (Sandbox Code Playgroud)

这一切都有效,但当我偶然发现它甚至与这个 DbContext 一起工作时,我感到震惊:

public class MyDbContext : DbContext
{
    public MyDbContext()
        : base("name=MyDbContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MyDbContext>(null);
        base.OnModelCreating(modelBuilder);
    }    


    public DbSet<Table1> Table1 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

或这个..

public class MyDbContext : DbContext
{
    public MyDbContext()
        : base("name=MyDbContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MyDbContext>(null);
        base.OnModelCreating(modelBuilder);
    }    


    public DbSet<Table2> Table2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

你能向我解释一下,为什么它有效?如何?

谢谢!

编辑。它不包括在内。我能够做到:

var tables2 = fni.Set<Table2>()
    .Where(t => t.Table2Id == 123456).ToList();
Run Code Online (Sandbox Code Playgroud)

只有这个:public DbSet<Table1> Table1 { get; set; }在 DbContext 中。它甚至不是 Table2!它们通过 FK 连接(定义没有改变)。所以这意味着,您必须只有一个表格“链”中的一张表格。那是对的吗?

Ale*_*xan 7

让我们看一下文档

我们有以下型号:

public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }

public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }

public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

和数据库上下文:

public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

但:

你可以省略DbSet<Enrollment>andDbSet<Course> 语句,它的工作原理是一样的。实体框架将隐式包含它们,因为 Student 实体引用 Enrollment 实体,而 Enrollment 实体引用 Course 实体。

附注。抱歉,我只是注意到这个问题与 EF Core 无关。但我认为无论如何它应该是真的。