在本教程中使用的软件版本
- Visual Studio 2013 年
- 4.5.NET
- 实体框架 (EntityFramework 6.1.0 NuGet 包) 6
- Windows Azure SDK 2.2(可选)
安装EntityFramework 6
从工具菜单上单击库的软件包管理器,然后单击程序包管理器控制台.
在软件包管理器控制台窗口中输入下面的命令:
Install-Package EntityFramework
该图像显示了 6.0.0 正在安装,但 NuGet 将安装最新的预发行版本的实体框架中,这起最新的更新的教程是 6.1.0。
在模型文件夹中创建一个名为Student.cs的类文件和模板代码替换为以下代码:
using System;
using System.Collections.Generic; namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
} ID属性将成为此类对应的数据库表的主键列。默认情况下,实体框架将解释命名的ID或类名ID作为主键的属性。
一般情况下,我们应该使用类名(表名)+ID作为主键,以保持与外键引用一致。其它字段直接用名词即可,无需添加首字母或类名。
Enrollments属性是一个导航属性。导航属性将保存与此实体相关的其他实体。在这种情况下,Student实体的Enrollments属性将保留所有的Enrollment实体的是该Student与实体相关的。换句话说,如果在数据库中的某一给定的Student行有两个相关的Enrollment行 (包含在其StudentID的外键列中的那个学生主键值的行),该Student实体的Enrollments导航属性将包含这两个Enrollment实体。 导航属性通常定义为virtual中,这样,他们可以利用某些实体框架功能,如延迟加载。(延迟加载稍后我将解释,读取相关数据教程稍后在本系列中)。 如果导航属性可以容纳多个实体 (如多对多或一对多的关系),其类型必须是一个列表,在其中可以添加、 删除和更新的如ICollection条目.
在模型文件夹中创建Enrollment.cs和现有的代码替换为以下代码:
namespace ContosoUniversity.Models
{
public enum Grade
{
A, B, C, D, F
} public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; } public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
} EnrollmentID属性将是主要的关键 ;此实体使用的类名ID模式而不是ID本身正如你看到的Student实体中。通常你会选择一个模式,并使用它在您的数据模型整个。在这里,变化说明了您可以使用任一模式。在以后的教程中,你会你会看到如何使用ID没有classname的情况下容易,而在数据模型中实现继承。 Grade属性是枚举。问号后Grade类型声明指示Grade属性是可以为 null。为 null 的品位是不同从零级 — — null 意味着 a 级不已知或没尚未被分配。 StudentID属性是一个外键,并在相应的导航属性是Student。Enrollment实体是与一个Student实体、 关联,因此该属性只能容纳一个单一的Student实体 (不同的Student.Enrollments导航属性你看到较早前,可容纳多个Enrollment实体)。 CourseID属性是一个外键,并在相应的导航属性是Course。Enrollment实体是与一个Course实体相关联。 实体框架解释财产作为外键属性,如果它被命名为< 导航属性名称 >< 主键属性名称 > (例如,StudentID为Student导航属性因为Student实体的主键是ID)。外键属性还可以进行命名相同只是< 主键属性名称 > (例如, CourseID因为 Course实体的主键是CourseID).
使用枚举在使用支架时并不生成下拉列表,但会在客户端和服务器端自动验证输入的是否是枚举列出的对应的数值。
<input class="text-box single-line" data-val="true" data-val-number="The field Credits must be a number." data-val-range="字段 Credits 必须在 0 和 5 之间。" data-val-range-max="" data-val-range-min="" data-val-required="Credits 字段是必需的。" id="Credits" name="Credits" type="number" value="" />
创建的数据库上下文
在 ContosoUniversity 项目中创建一个文件夹,右键单击解决方案资源管理器中的项目和单击添加,然后单击新文件夹。名称的新文件夹DAL (对于数据访问层)。在该文件夹中创建一个新的类文件命名为SchoolContext.cs,和模板代码替换为以下代码:
using ContosoUniversity.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions; namespace ContosoUniversity.DAL
{
public class SchoolContext : DbContext
{ public SchoolContext() : base("SchoolContext")
{
} public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
指定实体集 此代码创建一个DbSet属性为每个实体集。在实体框架术语中,实体集通常对应一个数据库表,和一个实体对应于表中的一行。 你可以省略DbSet<Enrollment>和 DbSet<Course>语句,它会的工作方式相同。实体框架将包括这些隐式因为Student实体引用Enrollment实体和Enrollment实体引用Course实体。 指定连接字符串 连接字符串 (其中你会以后将添加到 Web.config 文件) 的名称在传递给构造函数。
public SchoolContext() : base("SchoolContext")
{
} 您还可以通过在连接字符串而不是一个存储在 Web.config 文件中的名称。有关用于指定数据库使用的选项的详细信息,请参见实体框架-连接和模型.
如果您不显式指定的连接字符串或一个名称,实体框架假定连接字符串的名称与类名称相同。在此示例中的默认连接字符串名称,然后将SchoolContext
,你要指定的显式相同。
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
上面一行用于指定表名是单数形式。一般情况下,我们建立的实体类都应该是单数,所以,上面一行可以省略。
数据库优先时,也应该使用单数名词作为表名,以与惯例保持一致。
设置 EF,用测试数据初始化数据库
实体框架可以自动创建 (或删除并重新创建) 为您在应用程序运行时的数据库。您可以指定应该这样每次运行应用程序或模型是与现有的数据库不同步时,才。您也可以编写Seed
的一种方法,实体框架将自动调用来填充它的测试数据创建数据库后。
默认行为是创建一个数据库,只有当它不存在 (和抛出异常,如果模型已更改,数据库已经存在)。在本节中,您将指定该数据库应被删除并重新创建模型发生变化时。删除数据库将导致所有数据的丢失。这通常是确定在开发期间,因为Seed
的方法将运行时数据库重新创建,并且将重新创建您的测试数据。但在生产中你一般不想失去你的所有数据,每次您需要更改数据库架构。稍后你会看到如何通过使用代码第一次迁移更改而不是删除和重新创建数据库的数据库架构处理模型更改。
Entity Framework数据库初始化四种策略
策略一:数据库不存在时重新创建数据库 Database.SetInitializer<testContext>(new CreateDatabaseIfNotExists<testContext>()); 策略二:每次启动应用程序时创建数据库 Database.SetInitializer<testContext>(new DropCreateDatabaseAlways<testContext>()); 策略三:模型更改时重新创建数据库 Database.SetInitializer<testContext>(new DropCreateDatabaseIfModelChanges<testContext>()); 策略四:从不创建数据库 Database.SetInitializer<testContext>(null); Entity Framework数据库初始化示例 using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Web.Models.Mapping; namespace Web.Models
{
public class testContext : DbContext
{
static testContext()
{
Database.SetInitializer<testContext>(null);
} public testContext()
: base("Name=testContext")
{
} public DbSet<Person> People { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new PersonMap());
}
}
}
种子数据的添加,有两种方式,一种是在web.config中配置,一种是在Application_Start
中设置。
<entityFramework>
<contexts>
<context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
<databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Application_Start
中设置
Database.SetInitializer<SchoolContext>(new SchoolInitializer());
一些放在global中的设置,修改后需要重新启动WEB站点。
DropCreateDatabaseIfModelChanges
初始值设定项
公约:
实体类名用作表名,应以单数形式体现。
实体属性名用于列名。
被命名为ID或类名+ID的实体属性将作为主键。
CRUD (创建、 读取、 更新、 删除)
延迟加载:如果需要循环延迟加载项进行绑定,可以预先将相关数据一起加载然后进行循环,以减少访问数据库的次数,消耗系统性能。
因为ID
是主键值,插入的行时,SQL Server 将自动设置,可删除从绑定属性的ID
。来自用户的输入并不设置的ID
值。
Security Note: The ValidateAntiForgeryToken
attribute helps prevent cross-site request forgery attacks. It requires a corresponding Html.AntiForgeryToken()
statement in the view, which you'll see later.
controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student)
view:
@Html.ValidationSummary(true)
Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student
指定要绑定的属性列表可以防止客户端虚假提交无需从客户端获取的值,如经过计算后设置的值等。