学习Entity Framework 中的Code First

时间:2022-09-13 13:38:54

这是上周就写好的文章,是在公司浩哥的建议下写的,本来是部门里面分享求创新用的,这里贴出来分享给大家。

  最近在对MVC的学习过程中,接触到了Code First这种新的设计模式,感觉很新颖,并且也体验到了这种方式所带来的便利。这里将我的一些理解分享出来。

需要了解的概念

Ÿ POCO

  POCO(Plain Old CLR Object)的概念是从java的POJO借用而来,而两者的含义是一致的,不同的仅仅是使用的语言不一样。所以POCO的解释就是“Plain Old C# Object”。POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的对象。

Ÿ PO

  PO是指持久对象(persistant object持久对象)。持久对象实际上必须对应数据库中的entity,所以和POJO有所区别。比如说POJO是由new创建,由GC回收。但是持久 对象是 insert数据库创建,由数据库delete删除的。基本上持久对象   生命周期和数据库密切相关。另外持久对象往往只能存在一个数据库 Connection之中,Connnection关闭以后,持久对象就不存在了,而POJO只要不被GC回收,总是存在的。

Ÿ ORM

  ORM(Object/Relational Mapping) 对象关系映射,主要是把数据库中的关系数据映射称为程序中的对象

Ÿ NHibernate

  NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。所以NHibernate与 Entity Framework是很相近的。

Ÿ Entity Framework

  Entity Framework的全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Relational Mapping)框架。

其架构图如下:

学习Entity Framework 中的Code First

  在接手一个新项目时我们所熟知及习惯使用的设计方式,是在分析需求后开始创建数据库中的表,一旦表确定后变动不会太大或者几乎不再去更改表的结构,后面的模型编写及业务逻辑的编写都在这个基础上进行。这种方式称为Database First。

  而在2011四月发布的Entity Framework 4中存在三种工作方式,他们分别为:Code First,
Model First和Database First。其中本文要讨论的Code First就是新增的一种方式。

Code First

  为了支持以设计为中心的开发流程,EF4 还更多地支持以代码为中心
(code-centric) ,我们称为代码优先的开发,代码优先的开发支持更加优美的开发流程,它允许你:

在不使用设计器或者定义一个
XML 映射文件的情况下进行开发。

  ·允许编写简单的模型对象POCO
(plain old classes),而不需要基类。

  ·通过"约定优于配置",使得数据库持久层不需要任何的配置

  ·也可以覆盖"约定优于配置",通过流畅的
API 来完全定制持层的映射。

  Code First是基于Entity Framework的新的开发模式,原先只有Database First和Model
First两种。Code
First顾名思义,就是先用C#/VB.NET的类定义好你的领域模型,然后用这些类映射到现有的数据库或者产生新的数据库结构。Code
First同样支持通过Data Annotations或fluent API进行定制化配置。

其他两种设计方式

Ÿ   Database First是最老也是应用得最广泛的一种设计方式。如上文提到过的那样,Database
First这种方式的设计高度依赖于数据库中表的结构,根据表及表间的关系来创建模型。如果后期需求有所变更或者功能有很大变化的话,需要涉及到更改数据
库所付出的代价将会很大,因为之前编写好的代码将不再适用于新的表,我们必需重构以更改代码中的逻辑以适应更改之后的表。

Ÿ   Model
Firstj是创建ADO.NET实体对象以及它们之间的关系,然后再指定到数据库的映射。这个实体对象即为Model。

在MVC中使用CodeFirst

  这里我将用一个非常简单的例子来演示一下Code First在MVC中的使用,主要还是展示Code First
具体是怎么工作的。

  Note:你可能需要单独安装Entity Framework 4.1

  ADO.NET Entity Framework 4.1 安装文件下载地址:http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363

  下面我们开始这个例子。既然是Code
First,就是以代码为中心进行设计,所以我们并不关心具体的数据库构造到底是怎么样的。我们从分析需求开始,即我们要实现的功能。这里我仅仅是要实现
一个展示博客列表的页面,这里我们不关注CRUD的实现,因为这些都可以在MVC里自动生成。这里我们将看到,整个过程我们没有写sql语句,也没有用
sql server management studio
在数据库里进行表的设计,但我们运行程序时,这些需要的表就已经自动创建好了,并且我们在页面进行CRUD操作时,也是与数据库里面的数据是完全同步的。

  打开VS2010新建一个MVC3项目,注意环境要设为.Net Framework 4。这里我将项目命名为MvcBlog。

学习Entity Framework 中的Code First

  选择空的模板,View engine我们用ASPX。

学习Entity Framework 中的Code First

  因为Code First需要EntityFramework支持,项目创建好后在引用里面系统已经自动为我们引用了EntityFramework程序集,如果没有需要手动引用进来。

学习Entity Framework 中的Code First

(为了展示完整的目录层结构,在图片上我把中间很多引用去掉换以省略号代替,所以你看到这张图片时不要感到奇怪,我的VS不是特别定制版的)

  我们首先在Model中创建一个博客类来保存一篇博客的基本信息,它包含一个博客标识BlogId, 标题Title还有创建日期CreateDate。

在Model文件夹上右击选择Add->Class。

学习Entity Framework 中的Code First

  在Name中输入Blog再点击Add。

学习Entity Framework 中的Code First

  其中的代码如下:

学习Entity Framework 中的Code First
 1 namespace MvcBlog.Models
2
3 {
4
5 public class Blog
6
7 {
8
9 public int BlogId { get; set; }
10
11 public string Title { get; set; }
12
13
14
15 public DateTime CreateDate { get; set; }
16
17 }
18
19 }
学习Entity Framework 中的Code First

  同样的方法我们再新建一个类,命名为BlogEntities.cs,这个类跟Blog类的功能是不同的,我们将在代码里将它定义为从 DBContex继承,这样这个BlogEntities上下文类将扮演着与数据库沟通的重要角色,在这里面可以定义需要的表,项目运行后这些表将自动在 数据库创建。这里,我们用刚才定义好的Blog来定义一个Dbset,代码如下:

学习Entity Framework 中的Code First
1 public class BlogEntities:DbContext
2
3 {
4
5 public DbSet<Blog> Blogs { get; set; }
6
7 }
学习Entity Framework 中的Code First

 (注意:这里需要在文件顶部添加using System.Data.Entity引用语句才能使用DbContext及DbSet)

  上面我们把模型准备好了,现在定义Controller。但在进行这一步前,我们需要Ctrl+Shift+B编译一下程序,以便系统知道我们 之前定义好的Blog类和BlogEntities类。右击Controllers文件夹选择Add->Controller打开添加 Controller对话框,将其命名为HomeController(MVC的Controller,当然你也可以随便命名,只不过在打开网页时需要手 动输入路径),此刻数据库还没有被创建,并且呆会自动创建后里面也是空的没有数据,我们需要向里面添加一些数据,所以这里模板我们选择带有CRUD(增删 除改查)功能的,再将下面的模型类选为Blog,上下文类选为BlogEntities,系统会自动实现CRUD操作,不用我们手动编写。

(注意:之前必需编译一下,才能在这一步的下拉菜单里找到我们已经定义好的类)

学习Entity Framework 中的Code First

单击Add之后,生成的代码大概是这样:

  

  视图已经自动添加在了Views文件夹下,到此我们的程序已经能够工作了,虽然我们似乎什么都没做。在运行前我们可以打开Sql server management studio (或者在VS里用服务器管理器连接到你本地的数据库)查看一下以确定数据库里还没有我们程序里需要的Blog表。然后我们Ctrl+F5运行网站。

学习Entity Framework 中的Code First

  页面显示出了我们在Blog中定义的Title字段和CreateDate字段,但由于还没有数据来进行显示,所以只有标题。

  这个时候,我们断开数据库再重新连接,就会发现EF创建了一个程序命名空间为名称的数据库MvcBlog.Models.BlogEntities,里面包含我们用Dbset定义的Blogs表。表中的列也正好与我们在Blog类中定义的字段相对应。

学习Entity Framework 中的Code First

  仔细观察你会发现,它自动将BlogId定义为了主键,这是EF的convention在起作用,如果我们没有显示地指定数据库的连接字符串等 配置信息,这些值将会遵从EF里的约定进行取值,比如这里的数据库名 MvcBlog.Models.BlogEntities。

  这样的名称当然不是我们想要的,而且,如果我们本地安装了多个数据库实例的话,我们也希望指定项目将数据创建在我们想要的实例当中。要覆盖默认 的约定,我们只需在Web.config(注意:不是Views文件夹下的Web.config)里添加一下对数据库的配置信息,代码如下:

学习Entity Framework 中的Code First
<connectionStrings>

    <add name="BlogEntities"

        connectionString="server=(local)\sqlexpress;database=MvcBlog;integrated security=true;"

        providerName="System.Data.SqlClient"/>

  </connectionStrings>
学习Entity Framework 中的Code First

  注意上面的name应和Models中的定义的上下文类名称相同,这样才能使EF正常工作。server换成你本机数据库实例的名字。现在我们可以看到在先前那个数据库上方它生成了我们重新命名的数据库。

学习Entity Framework 中的Code First

  重新运行程序,我们在页面中点击Create New来添加几条数据。

学习Entity Framework 中的Code First

  添加完数据后我们再返回去看数据库中的变化。

学习Entity Framework 中的Code First

  如图,数据库中已经保存了我们在页面上添加的数据。

  到这里大家已经看到了Code First 设计方式的大概过程。现在我们来回顾一下,之前所做的操作,将会更加明白这一过程是怎样进行的,特别是代码优先是如何做到在没有数据库支持的情况下先建立数据模型,然后再对数据库进行操作的。

  首先我们在Models中创建了所需要的数据模型Blog类,里面包含的字段将映射到以后数据库表中的相应列。

  接下来同样是在Models文件夹中,我们定义了一个最关键的BlogEntities上下文类,它继承自System.Data.Entity下的DbContext,它将我们的数据模型映射到数据库中,将代码中的数据持久化。

  最后,在页面上进行添加数据时,页面将表单数据通过Blog类型传回Controller里面相应的方法,这里是处理Post回传的 Create Action,它接收传回来的数据,通过调用db.SaveChanges()进行了数据的保存。这里db是BlogEntities上下文类的一个实 例。通过BlogEntities上下文类,我们进行的RUD操作将反应到数据库中,完成了从代码到数据库的更新过程。

Data Annotations

  接着上面的例子,试想,一篇博客一般还包含有分类信息,比如日志,随笔等。现在我们就去添加这样一个类,保存博客的分类信息,相应地,我们还应更新一下我们的博客类,让它包含一个分类属性,这样我们就可以指定一篇博客的所属分类了。

  这里将看到如何通过Code First创建表间的外键关系约束,以及定义表中列的其他信息,比如显示的信息,

  我们在Models文件夹中继续添加一个名为Category的类,它包含一个分类标识属性CategoryId, 一个分类名属性CategoryName。代码如下:

学习Entity Framework 中的Code First
 1 namespace MvcBlog.Models
2
3 {
4
5 public class Category
6
7 {
8
9 public int CategoryId { get; set; }
10
11 public string CategoryName { get; set; }
12
13 }
14
15 }
学习Entity Framework 中的Code First

  更新Blog类:

学习Entity Framework 中的Code First
 1 namespace MvcBlog.Models
2
3 {
4
5 public class Blog
6
7 {
8
9 public int BlogId { get; set; }
10
11 public string Title { get; set; }
12
13 public DateTime CreateDate { get; set; }
14
15 public int CategoryId { get; set; }
16
17 }
18
19 }
学习Entity Framework 中的Code First

  我们向其中添加了一个CategoryId属性,下面设置它为引用自Category中CategoryId的外键。

  这里有两个方法Data Annotation 和 Fluent API用于实现这种到数据库的映射,这里只讨论Data Annotation。

  由于CategoryId将会成为Blog到Category的导航属性,所以,除了要在Blog中添加CategoryId外,还需要添加一个类型为Category的属性,这样,在Blog中才会有一个来自Category中CategoryId的声明。

学习Entity Framework 中的Code First
 1 public class Blog
2
3 {
4
5 public int BlogId { get; set; }
6
7 public string Title { get; set; }
8
9 public DateTime CreateDate { get; set; }
10
11 public int CategoryId { get; set; }
12
13 public Category Category { get; set; }
14
15 }
学习Entity Framework 中的Code First

  在使用Data Annotation添加外键属性前需要添加System.ComponentModel.DataAnnotations命名空间到Blog类。然后我们就可以在CategoryId上面添加一个外键属性了。更改后的代码如下 :

学习Entity Framework 中的Code First
public class Blog

     {

         public int BlogId { get; set; }

         public string Title { get; set; }

         public DateTime CreateDate { get; set; }

         [ForeignKey("CategoryId")]
public int CategoryId { get; set; } public Category Category { get; set; } }
学习Entity Framework 中的Code First

  同时更新我们的BlogEntities对象:

学习Entity Framework 中的Code First
1 public class BlogEntities:DbContext
2
3 {
4
5 public DbSet<Blog> Blogs { get; set; }
6
7 public Category Categories { get; set; }
8
9 }
学习Entity Framework 中的Code First

  这时当我们运行程序时,会报错,如图:

学习Entity Framework 中的Code First

  因为之前运行程序时已经创建了数据库了,而现在我们在对模型进行更改后,它无法完全将更改之后的模型映射到之前的数据库,所以会出错。从错误提 示中已经给出了解决办法。要么手动删除之前创建好的数据库,要么使用DropCreateDatabaseIfModelChanges 的一个实例来对数据库进行初始化。需要注意的一点是,在商业开发中,第二种方法要小心使用,因为它会把之前的数据库自动删掉重新创建,而如果你之前保存有 大量信息在里面的话将无法挽回。

  这里我们不想每次在修改模型之后都手动去删除,所以用第二种方法将十分简便,只需到Global.asax文件的Application_Start()方法里面添加如下一行即可。

学习Entity Framework 中的Code First
 1 protected void Application_Start()
2
3 {
4
5 Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BlogEntities>());
6
7 AreaRegistration.RegisterAllAreas();
8
9
10
11 RegisterGlobalFilters(GlobalFilters.Filters);
12
13 RegisterRoutes(RouteTable.Routes);
14
15 }
学习Entity Framework 中的Code First

  这样,模型改变之后,它会删除掉原来的数据库重新创建。

  我们再次运行程序,然后再去数据库看,第二张表Category已经添加进去了,并且在Blog表里面,也出现了一个CategoryId外键,正如我们所想要的那样。

学习Entity Framework 中的Code First

需要注意的地方

  一个就是性能问题,使用edm designer从数据库来生成的ObjectContext,它会把很多东西存在CSDL,MSL,SSDL文件里,比如一些mapping信息,当页 面load时需要先从EDM文件里来load这些metadata,而使用Code-first是从Assembly里load数据,这样应该会节省不少 时间。但另一方面,EF自动生成的CONTEXT实体类会附带很多冗余信息,使得文件相对臃肿,在读取实体类中的信息时会在搜索上耗费不必需的时间。关于 性能问题具体可阅读一下参考中的第一篇文章。

  另外就是现在Code First应用得不是很多,就现在学习中碰到的例子来看,大部分都是Database First方式的。由于这是伴随微软新一代的EF4.1推出的设计方式,必定有其优越性,所以以后的项目中还是可以尝试用这种方式来进行设计。

后记

  我也是初学者,研究得不是很深刻,借鉴了许多别人的经验与分享,再加上自己的创新理解,肯定有不恬当的地方,权当加深自己的理解,与大家共同学习。

可以参考的一些文章

1.WCF和Entity framework 发现的性能问题

http://www.cnblogs.com/GaryChen/archive/2010/02/06/1664912.html

2.Entity Framework 4中的Code-First, Model-First和Database-First模式

http://www.cnblogs.com/n-pei/archive/2010/08/12/1797751.html

3.Code-First Development with Entity Framework 4

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

4.ADO.NET Entity Framework

http://en.wikipedia.org/wiki/ADO.NET_Entity_Framework

5.A Code First Example using Entity Framework 4

http://chris.widdowson.id.au/?p=746#

6. Entity Framework At-a-Glance

http://msdn.microsoft.com/en-us/data/aa937709

7. Nadege Deroussen在codeproject的三篇文章

Entity Framework Code First: Let's Try It

http://www.codeproject.com/Articles/318010/Entity-Framework-Code-First-Let-s-Try-It

EF Code First: Add a Foreign Key relationship

http://www.codeproject.com/Articles/319366/EF-Code-First-Add-a-Foreign-Key-relationship

EF Data Annotations and Code Fluent

http://www.codeproject.com/Articles/368164/EF-Data-Annotations-and-Code-Fluent

Feel free to repost but keep the link to this page please!

学习Entity Framework 中的Code First的更多相关文章

  1. 转载:学习Entity Framework 中的Code First

    看完觉得不错,适合作为学习资料,就转载过来了 原文链接:http://www.cnblogs.com/Wayou/archive/2012/09/20/EF_CodeFirst.html 这是上周就写 ...

  2. Entity Framework 中的Code First 中引入数据库函数

    1,在项目中添加CodeFirstStoreFunctions包: Install-Package EntityFramework.CodeFirstStoreFunctions 2,注册注册函数,F ...

  3. Entity Framework工具POCO Code First Generator的使用

    在使用Entity Framework过程中,有时需要借助工具生成Code First的代码,而Entity Framework Reverse POCO Code First Generator是一 ...

  4. Entity Framework 6&period;0 Code First(转)

    源自:http://www.cnblogs.com/panchunting/tag/Code%20First/ 1 Conventions 2 Custom Conventions 3 Data An ...

  5. Entity Framework工具POCO Code First Generator的使用&lpar;参考链接:https&colon;&sol;&sol;github&period;com&sol;sjh37&sol;EntityFramework-Reverse-POCO-Code-First-Generator&rpar;

    在使用Entity Framework过程中,有时需要借助工具生成Code First的代码,而Entity Framework Reverse POCO Code First Generator是一 ...

  6. Entity Framework 教程——Entity Framework中的实体类型

    Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...

  7. 关于Entity Framework中的Attached报错相关解决方案的总结

    关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...

  8. 关于Entity Framework中的Attached报错的完美解决方案终极版

    之前发表过一篇文章题为<关于Entity Framework中的Attached报错的完美解决方案>,那篇文章确实能解决单个实体在进行更新.删除时Attached的报错,注意我这里说的单个 ...

  9. Entity Framework 6&period;x Code Frist For Oracle 实践与注意点

    Entity Framework 6.x Code Frist For Oracle 实践与注意点 开发环境 Visual Studio.net 2015/2017 Oracle 11g/12c 数据 ...

随机推荐

  1. centos7 nginx配置httpsCenos&lpar;6&period;6&sol;7&period;1&rpar;下从源码安装Python&plus;Django&plus;uwsgi&plus;nginx环境部署(二)

     1.yum安装nginx 下载对应当前系统版本的nginx包(package) # wget  http://nginx.org/packages/centos/7/noarch/RPMS/ngin ...

  2. SpringMVC&plus;MyBatis(最新)

    目前主流的Web MVC框架,除了Struts这个主力 外,还有Spring MVC,主要是由于Spring MVC配置比较简单,使用起来也十分明了,非常灵活,与Spring 集成较好,对RESTfu ...

  3. sql server查询出的结果中添加一列序列行

    select row_number()over(order by id) as rownum ,[UserName] ,[Password] ,[Mobile] ,[Email] ,[Sex] ,[C ...

  4. 深入理解Oracle的imp&sol;exp 和各版本之间的规则

    Oracle数据中IMP/EXP工具可用于对数据进行迁移.IMP命令用于把Dmp文件从本地导入到远程数据库服务器,而EXP命令则是把数据从远程数据库服务器导出到本地的Dmp文件.其功能相当于Oracl ...

  5. &lpar;转&rpar;Maven实战(五)坐标详解

    1.为什么要定义Maven坐标      在我们开发Maven项目的时候,需要为其定义适当的坐标,这是Maven强制要求的.在这个基础上,其他Maven项目才能应用该项目生成的构件. 2.Maven坐 ...

  6. telnet命令使用详解

    telnet命令用于登录远程主机,对远程主机进行管理.telnet因为采用明文传送报文,安全性不好,很多Linux服务器都不开放telnet服务,而改用更安全的ssh方式了.但仍然有很多别的系统可能采 ...

  7. CentOS 7安装MongoDB

    1 下载安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.4.tgz 2 解压 .tgz 3 将解压包 ...

  8. 学习excel的使用技巧三快捷键和思路

    快捷键 CRTL+回车 是多行执行 思路 关于公式 在空白出 写= 即开始写公式 excel第一行 就是行标 比如 A1 就是excel 表格中第一个 比如来个乘法 =A1*12+b1*13 求和更简 ...

  9. java07接口与继承动手动脑

    1.源代码: package Work; class A{ public A(){ System.out.println("Class A."); } public A(Strin ...

  10. TensorRT下安装pycuda

    为了模型小型化,效率更高,使用TensorRT进行优化.前提是你必须要安装pycuda,可是费了我一番功夫.做一个笔记如下: 1.参考网址: https://wiki.tiker.net/PyCuda ...