EF Code-First示例
在前一章中,我们在项目中安装了entity framework。在这里,我们将创建一个简单的code-first示例。
让我们假设要为XYZ学校创建一个简单的应用程序。这个学校应用程序的用户应该能够添加和更新学生、成绩、教师和课程信息。
与其先设计数据库表,不如在需要时开始为school domain创建类。首先,创建Student和Grade类,其中每个Student都与一个Grade相关联,如下所示。这被称为一对多关系。
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime? DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
public Grade Grade { get; set; } //虽然Student中没有写Grade的外键,但是EF会为我们自动生成一个外键
}
创建Grade类,如下所示。
public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
public ICollection<Student> Students { get; set; }
}
现在,我们已经完成了学校应用的初始域类。
Code-First方法还需要一个上下文类,它应该派生自DbContext类。创建一个上下文类,如下所示。它派生于DBContext类,并为你想要成为模型一部分的类型公开DbSet属性,例如在本例中是Student和Grade类。DbSet是实体类的集合(又名实体集),所以我们用实体名的复数形式来表示属性名,比如Students和Grades。
namespace EF6Console
{
public class SchoolContext: DbContext
{
public SchoolContext(): base()
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Grade> Grades { get; set; }
}
}
现在,我们已经完成了code-first所需的类。现在我们将使用上下文类添加一个学生,如下所示。
namespace EF6Console
{
class Program
{
static void Main(string[] args)
{
using (var ctx = new SchoolContext())
{
var stud = new Student() { StudentName = "Bill" };
ctx.Students.Add(stud);
ctx.SaveChanges();
}
}
}
}
试一试
如果运行该应用程序,您将看到一个学生成功地插入到数据库中。
但是数据库在哪里?哪些是表及其列?
这就是EF Code-First API的美妙之处。它根据上下文类的父类构造函数中传递的参数创建数据库。由于我们没有在上下文类的构造函数中传递任何参数,因此它创建了EF6Console。本地SQLEXPRESS数据库中的SchoolContext数据库,如下所示。它还在这个数据库中创建了两个表,基于上面定义的Student和Grade域类的Students和Grades。
正如您在上图中看到的,它已经创建了Students和Grades表,每个表都包含具有适当数据类型和长度的列。列名和数据类型匹配各自域类的属性。并将studententid和GradeId设为主键pk,将Grade_GradeId列设为外键FK。
通过这种方式,无需首先创建数据库,就可以开始编写最终将从域类创建数据库的应用程序。
注意:如果您修改这些类并再次运行应用程序,那么它将抛出以下异常。
您需要在上下文类中定义数据库初始化策略,以便修改域类并在本地运行应用程序。
您一定想知道它是如何用PK和FK创建具有适当数据类型和长度的列的,对吧?答案是使用code-first的默认约定。
参考
https://www.entityframeworktutorial.net/
https://msdn.microsoft.com/