【问题标题】:Database-first approach in Entity Framework without auto generated code没有自动生成代码的实体框架中的数据库优先方法
【发布时间】:2014-09-03 19:17:37
【问题描述】:

不知道有没有办法 提前将数据库优先方法与手动生成的类(模型)一起使用(就像代码优先方法一样), 但不使用实体框架使用数据库优先方法创建的自动生成代码? 我有 3 个班级(其中前两个学生和课程有多对多关系),代表模型: 第一个是学生:

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; }

}

另外,我使用 VS 2013 中的 LocalDb 功能创建了数据库

我有 3 张桌子: 课程:

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,
)

StudentToCourses 关系表:

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) 
)

不幸的是,我对这种方法没有运气,我确实获得了学生的数据,但我没有从关系表中收到数据,而且我无法收到每个学生的所有相关成绩。

我在 google 和 stackoverflow 中搜索了相关主题,但所有这些主题对我都没有帮助,尽管我在 topic 中找到了上面的示例。

【问题讨论】:

标签: c# sql entity-framework


【解决方案1】:

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

你没有得到数据的原因是因为没有发生延迟加载。你的说法是

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

这需要延迟加载,因为FirstOrDefault() 语句执行查询的第一部分。它呈现一个Student,随后访问StudentToCourses。但是这些不会加载,因为集合不是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;

【讨论】:

  • 感谢您的回答,但是...首先,据我所知,Include 方法将字符串作为其传入参数。其次,我实际上将 StudentToCourses 定义为虚拟的(如您所建议的),现在我得到一个异常“无效的对象名称'dbo.StudentToCourses'”这里是代码:var studentGrades = _context.Students.Include("StudentToCourses").Where(s =&gt; s.Name == "John").FirstOrDefault().StudentToCourses;
  • include参数取决于你使用的EF版本,或者你是否有using System.Data.Entity.DbExtensions。您的 DDL 脚本中的表名是 StudentsToCourses(带有“s”的学生)。
  • 我使用的是 EF 6.0,关于 System.Data.Entity.DbExtensions,很好,谢谢,我忘记了,你说得对。我也试过 StudentToCourses,它抛出了同样的异常。
【解决方案2】:

是的,你可以。您只需要一个没有初始化策略的上下文(因此它不会尝试创建或迁移您现有的数据库):

public class ExistingDatabaseContext : DbContext
{
    public ExistingDatabaseContext()
        : base("ExistingDatabaseConnectionStringName")
    {
        Database.SetInitializer<ExistingDatabaseContext>(null);
    }

    // DbSets here for your "code-first" classes that represent existing database tables
}

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

【讨论】:

  • 感谢您的回答,但它对我不起作用,我仍然得到一个空集合`public ICollection StudentToCourses`。我认为由于某种原因 EF 不喜欢 Intermediate Class\Table 存在一些问题。
猜你喜欢
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
相关资源
最近更新 更多