好久没写EF的东西,使用起来也觉得生疏,最近EF5发布,学习了一下新知识,总结一番。

1.Entity Framework架构原理回顾

什么是EF:EntityFrameWork是微软一个开源的ORM(对象关系映射)框架,是微软主推的数据存储技术,常用于构建数据存储层,使应用程序以对象模型的方式访问关系数据库的内容。

EF的架构和原理:EF的核心内容是EDM,具体可参考前一篇内容。可以理解为它是一个ADO.NET的增强版,它的底层是ADO.NET provider,上层则是应用程序,它提供了更灵活,更简单方便的数据存取方式。

EF的优点:它是一个开源框架,支持多种数据库(目前看来最稳定的是SQL Server,而Oracle的支持一直不太完美),将应用程序和数据库结构很好的分隔开,支持多种开发模式。

EF的缺点:它是在ADO.NET的基础上做的扩展,性能比ADO.NET有所损失,但是只要合理的利用EF,避免一些劣质查询语句带来的损耗,还是能有效提高EF性能。

2.Entity Framework开发模式

EF提供了四种开发模式,具体如下:

Code First(New DataBase) :在代码中定义类和映射关系并通过model生成数据库,使用迁移技术更新数据库。

Code First(Existing DataBase):在代码中定义类和映射关系,给逆向工程提供工具。

Model First:在设计器中创建Model,并用Model生成数据库。所有的类由Model自动生成。

DateBase First:在设计器中逆向生成Model,并有Model自动生成所有的类。

这样一看可能不太理解,这四种开发模式究竟如何使用,在那些地方使用,现在来一一分析。

2.1 DataBase First 模式

EF最早使用的开发模式也是最简单的开发模式,它通过已存在的数据库逆向分析出Model,并获取Class信息。这种方式的好处是开发简单,便于管理,不便之处是限制了开发人员对Model的修改,当然,为此EF在4.0版本也提供了新的功能,支持POCOs,让开发人员能够方便的对数据库进行操作。关于POCOs的信息可以看着一个系列http://blogs.msdn.com/b/adonet/archive/2009/05/21/poco-in-the-entity-framework-part-1-the-experience.aspx

使用方法:

  1. 在VS工程中,右键—添加—新建项—数据,然后选择ADO.NET实体数据模型

  2. 选择“从数据库生成”

3.选择需要连接的数据库引擎和数据库,并勾选需要包含的对象即可

2.2 Model First 模式

这个模式在实际应用中并不多见,如果建立一个小型数据库模型,可以尝试这种方法,它需要我们在VS的设计其中定义Model,然后通过Model建立数据库。

使用方法:

1.添加一个ADO.NET实体数据模型并选择“空模型”

2.在该Model的设计器下右键–新增–实体

3.给该实体填写名称和属性

4.在该实体上右键–新增–标量属性,填写属性名称

5.重复上述步骤建立若干个实体,然后在设计器空白处右键–新增–关联,填写关联名称,关联实体和对应关系

6.在设计器空白处右键–根据模型生成数据库,并按照向导提示,完成创建,最后得到一个SQL脚本,将该脚本放入SQL Server Management Studio执行,就完成了数据库的建立。

个人感觉Model First有点类似Power Designer建模的意思。

2.3 Code First - New DataBase 模式

这个模式对于中小型项目比较适用,代码相对简洁清爽,但Code First对于数据库更新是件比较麻烦的事。先看看Code First如何使用。

1.创建一些我们需要的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class User
{
[Key]
public string Username { get; set; }
public string DisplayName { get; set; }
}

2.创建一个继承DbContext的类,该类中需要使用DbSet来把我们刚才创建的类放在实体集中

1
2
3
4
5
6
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}

3.给BloggingContext一个实例,就可以操作,并通过SaveChanges方法保存

1
2
3
4
5
6
7
8
9
10
11
BloggingContext db = new BloggingContext();
Console.Write("Enter a name for a new Blog: ");
var name = Console.ReadLine();
var blog = new Blog { Name = name };
db.Blogs.Add(blog);
Random ran=new Random();
User user = new User();
user.Username = "user" + ran.Next(1, 1000);
user.DisplayName = "display name for " + user.Username;
db.Users.Add(user);
db.SaveChanges();

4.运行SQL Server Management Studio,(必须是存在sqlexpress)看到新建的数据库,并发现它的命名是“DbContext命名空间.DbContext类名“

5.我们可以通过一些手段让数据库建立在其他地方

在App.config中修改信息如下

1
2
3
4
5
<configuration>
<connectionStrings>
<add name="BloggingCompactDatabase" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=Blogging.sdf"/>
</connectionStrings>
</configuration>

修改BloggingContext构造函数

1
public class BloggingContext : DbContext { public BloggingContext() : base("BloggingCompactDatabase") { } }

当然也可以直接在BloggingContext 里做修改而不用App.config

1
2
3
4
5
6
public class BloggingContext : DbContext
{
public BloggingContext(string conn) : base(conn)
{
}
}

然后调用BloggingContext时直接传连接字符串进去即可。

补充:Code First 设置主外键以及字段属性

在前面的两个设计方法中都可以比较方便的设置数据表主外键和字段属性,就第一感觉来说,使用Code直接设置数据表是比较麻烦的事。但事实上我们可以通过C#的Atrribute机制来完成这些设置。

例子1:ID为主键,自动增量

1
2
[Key,DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }

例子2:Name为必填项,最长为50

1
2
3
[Required]
[MaxLength(50)]
public string Name { get; set; }

关于更多CodeFirst建立数据表关系的文章可以参考http://www.cnblogs.com/Gyoung/archive/2013/01/22/2869782.html

2.4 Code First - Existing DataBase 模式

通过使用EF PowerTools逆向生成数据库所有的表再由应用程序修改使用。但在EF5中,EF PowerTools还处于测试阶段,这里就不针对这种方法做进一步介绍了。

3.使用Code First**开发模式后如何更新数据库

我们可以看到在Code First中,通过代码来构建数据库model然后生成数据库,那如果要求数据库结构改变(增加属性或者类,对属性和类重命名,对列或者表重命名,删除属性

),实体类改变了,我们也就要通过一些方法来更新数据库。

例如我们在Code First的例子中把Blog类的Name改成UserName,然后运行。会发现报错:

这时候我们就需要更新数据库,方法是:

1.安装VS的Nuget。打开Nuget控制台,输入Enable-Migrations启用数据库迁移。如果已经启用,控制台会提示“Migrations have already been enabled in project ‘*‘. To overwrite the existing migrations configuration, use the -Force parameter.”

2.标记迁移点,输入Add-Migration *,星号为迁移点名称,可自定义。

3.输入Update-Database完成更新。

此时再执行程序,则不会再出现报错,数据库也更新完毕了。如果想回退到某一次的迁移点,只需要在Nuget控制台中输入 Update-Database –TargetMigration:”***“ 星号为迁移点名称。另外可以通过Script参数生成脚本,例如Update-Database -Script -SourceMigration:”**“ -TargetMigration:”**“ 这样就会生成一个sql脚本而不是直接更新数据库。

当然,如果觉得操作控制台的指令太多不方便,可以使用自动迁移功能。方法如下:

1.打开 Migrations文件夹下的Configuration.cs,修改代码为

1
2
3
4
public Configuration()
{
AutomaticMigrationsEnabled = true;
}

2.如果需要更新数据库,只需要在Nuget控制台输入Update-Database即可,如果提示“Automatic migration was not applied because it would result in data loss” ,则

在Update-Database 后面加 -Force参数即可。注意,这样并不会引起数据丢失。

以上便是对EF开发模式的一个小结,相关的细节问题将会在以后的随笔中介绍。