实体框架中没有自动生成代码的数据库优先方法
本文关键字:数据库 方法 代码 自动生成 框架 实体 | 更新日期: 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
}
请记住,此上下文将无法进行迁移或任何其他形式的初始化,因此,如果您也有真正的代码优先表,则需要一个单独的上下文来管理这些表。