实体框架中没有自动生成代码的数据库优先方法

本文关键字:数据库 方法 代码 自动生成 框架 实体 | 更新日期: 2023-09-27 18:20:36

我想知道,如果有什么办法,为了将数据库优先方法与预先手动生成的类(模型)一起使用(就像代码优先方法一样),但在不使用自动生成代码的情况下,哪个实体框架使用数据库优先的方法创建?我有三个班(前两个是学生和课程之间的多对多关系),这代表了模型:第一个是学生:

public class Student
{
    public int StudentID  { get; set;}
    public string Name  { get; set;}
    public DateTime BirthDate { get; set;}
    public ICollection<StudentToCourse> StudentToCourses { get; set; }
    public Student()
    {
        StudentToCourses = new List<StudentToCourse>();
    }
}

然后课程:

    public class Course
{
    public int CourseID { get; set; }
    public string CourseName { get; set; }
    public ICollection<StudentToCourse> StudentToCourses { get; set; }

    public Course()
    {
        StudentToCourses = new List<StudentToCourse>();
    }
}

以及具有附加属性的关系/中级课程StudentToCourse:

    public class StudentToCourse
{
    [Key, Column(Order = 0)]
    public int StudentID { get; set; }
    [Key, Column(Order = 1)]
    public int CourseID { get; set; }
    [Key, Column(Order = 2)]
    public DateTime Date { get; set; }
    public virtual Student Student { get; set; }
    public virtual Course Course { get; set; }
    //public ICollection<Student> Students { get; set; }
    //public ICollection<Course> Courses { get; set; }
    public int Grade { get; set; }
}

此外,我创建了数据库,使用VS2013中的LocalDb功能

我有三张桌子:课程:

CREATE TABLE [dbo].[Courses]
(
[CourseID] INT NOT NULL PRIMARY KEY IDENTITY,
[CourseName] NVARCHAR(100) NOT NULL,
)

学生:

CREATE TABLE [dbo].[Students]
(
[StudentID] INT NOT NULL PRIMARY KEY IDENTITY,
[Name] NVARCHAR(50) NOT NULL,
[BirthDate] DATETIME NOT NULL,
)

学生与课程关系表:

CREATE TABLE [dbo].[StudentsToCourses]
(
[StudentID] INT REFERENCES Students(StudentID) NOT NULL,
[CourseID] INT REFERENCES Courses(CourseID) NOT NULL,
[Date] DATETIME NOT NULL,
[Grade] INT NOT NULL,
PRIMARY KEY (StudentID, CourseID, Date) 
)

不幸的是,我在这种方法上运气不佳,我确实得到了学生的数据,但我没有从关系表中收到数据,也不能收到每个学生的所有相关成绩。

我在谷歌和stackoverflow中搜索了相关的主题,但所有这些主题对我没有帮助,尽管我在这个主题中找到了上面的例子。

实体框架中没有自动生成代码的数据库优先方法

正如我所怀疑的,问题不在于是否可以独立地拥有数据库和类模型。你当然可以!所有这些生成工具和迁移工具只服务于一个目标:让生活更轻松,帮助您保持两个模型的同步。但你自己也可以做这项工作。最终的结果总是:两个模型在运行时不会相互作用。(不互动?不,不是这样。必须有一个中间人,一个ORM,来连接两个世界。)

您无法获取数据的原因是不会发生延迟加载。您的声明是

var listOfGrades = _context.Students.Where(s => s.Name.StartsWith("J"))
                   .FirstOrDefault().StudentToCourses;

这需要延迟加载,因为FirstOrDefault()语句执行查询的第一部分。它呈现一个CCD_ 2,该CCD_。但由于集合不是virtual,因此不会加载这些。应该是

public virtual ICollection<StudentToCourse> StudentToCourses { get; set; }

这使EF能够覆盖能够延迟加载的动态代理对象中的集合。

当然,在一个语句中获取集合更有效,例如:

var listOfGrades = _context.Students.Include(s => s.StudentToCourses)
                   .Where(s => s.Name.StartsWith("J"))
                   .FirstOrDefault().StudentToCourses;

可以。你只需要一个没有初始化策略的上下文(这样它就不会试图创建或迁移你现有的数据库):

public class ExistingDatabaseContext : DbContext
{
    public ExistingDatabaseContext()
        : base("ExistingDatabaseConnectionStringName")
    {
        Database.SetInitializer<ExistingDatabaseContext>(null);
    }
    // DbSets here for your "code-first" classes that represent existing database tables
}

请记住,此上下文将无法进行迁移或任何其他形式的初始化,因此,如果您也有真正的代码优先表,则需要一个单独的上下文来管理这些表。