EntityFramework5学习
在开发面向数据的软件时我们常常为了解决业务问题实体、关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案。ADO.NET Entity Framework是.NET开发中一种由ADO.NET驱动的ORM框架,使用Entity Framework开发人员可以不必考虑数据的基础数据表和列,在处理数据时能够以更高的抽象级别进行工作,并能够以相对传统开发编写更少的代码来创建和维护应用程序。
我们知道面向对象的编程与数据存储系统的交换提出了一个难题:类结构通常同关系数据表组织结构相近但又不同。例如数据中可能使用一个外键表示一个实体与另一个实体的关系,但是对于类而言我们通知会在类中定义一个属性来描述这种关系。对于这个问题当前ORM框架一般选择通过将面向对象的类和属性映射到关系表和列来弥补这种不足。但是Entity Framework并没有采取这种方式而是将逻辑模型中的表、列和外键约束映射到概念模型中的实体和关系,实体数据模型工具再基于概念模型生成可扩展的数据类。这些类派生自基类,而基类提供服务以将实体具体化为对象并进行跟踪和保存。这样一来开发人员不仅可以很方便的对数据类进行扩展而且可以像处理关联对象一样处理实体和关系。
三种编程方式
Entity Framework4.1之前EF支持“Database First”和“Model First”编程方式,从EF4.1开始EF开始支持支持“Code First”编程方式,今天简单看一下EF三种编程方式。
开始介绍这三种EF操作方式之前,首先在Visual Studio 2013中建立一个数据库连接,这里我们以“AdventureWorks”数据库为例:

Database First
“Database First”模式我们称之为“数据库优先”,前提是你的应用已经有相应的数据库,你可以使用EF设计工具根据数据库生成数据数据类,你可以使用Visual Studio模型设计器修改这些模型之间对应关系。
首先创建一个控制台应用程序,然后右键添加新建项,选择“ADO.NET Entity Data Model”,名称输入AdventureWorksContext:

接着选择从数据库生成:

下一步,选择数据库连接“SQL2008.AdventureWorks.dbo”:

点击下一步,然后选择“Person”和“PersonPhone”表:

创建完模型之后,你会发现Visual Studio自动为你生成了“Perrson”、“PersonPhone”两个实体类和一个“AdventureWorksContext”数据库上下文操作类:

下面简单的看一下如何使用EF进行数据查询,通过下面的代码我们可以看到EF对于数据的操作入多么优雅:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DatabaseFirst
{
class Program
{
static void Main(string[] args)
{
using (var db = new AdventureWorksEntities())
{
IQueryable<Person> persons = from people in db.People
where people.LastName == "Sánchez"
select people;
foreach (Person p in persons)
{
Console.WriteLine("first name is :{0}", p.FirstName);
if (p.FirstName == "Angela")
{
p.AdditionalContactInfo = "other info";
}
} var persons2 = from people in db.People
where people.LastName == "Sánchez" && people.FirstName == "Angela"
select people;
if (persons2.Count() > 0)
{
Console.WriteLine("additional contact information is :{0}", persons2.First().AdditionalContactInfo);
}
//上面虽然可以查出来AddtionalContactInfo,但是实际省并未保存到数据库,具体保存方法在此不再详细描述
}
}
}
}
执行结果如下图:

![]() |
注意:如果你的数据库表结构发生改变后,只需在模型设计视图空白处右键,选择“从数据库更新模型”接着按照向导操作即可。 |
Model First
Model First我们称之为“模型优先”,这里的模型指的是“ADO.NET Entity Framework Data Model”,此时你的应用并没有设计相关数据库,在Visual Studio中我们通过设计对于的数据模型来生成数据库和数据类。
首先创建一个控制台应用程序,右键添加新建项,选择“ADO.NET Entity Data Model”,名称输入AdventureWorksContext:

接着选择空模型:

在模型设计视图中,添加新实体:

输入实体对应的属性:

添加,两个Scalar属性:“Customer”和“OrderDate”;同样的方式添加第二个实体“OrderDetail”,并添加“Product”和“UnitPrice”属性:

接下来我们添加二者之间的关系,“Order”和“OrderDetail”是一对多的关系,“Order”可以通过“OrderDetails”属性访问“OrderDetail”实体,“OrderDetail”可以通过“Order”属性访问“Order”实体,并且添加了一个外键约束到“OrderDetail”中:

添加过关系后:

到目前为止Model First中的Model已经创建结束,下面就需要生成到数据库了,在模型设计视图空白处选择“从模型生成到数据库…”:

选择数据库连接,点击下一步,你将会看到生成的sql语句:

点击完成,不出意外的话将打开生成的脚本,当然你也可能会出现如下错误,请下载最新的SQL Server Data Tool(我本地VS2012,数据库SQLServer2008R2出现了下面的提示,下载更新即可,建议直接下载镜像文件):

此时生成了数据库上下文和实体类,并且打开了建表的脚本:

打开的数据库脚本:

然后右键选择执行即可。
然后编码查询一下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ModelFirst
{
class Program
{
static void Main(string[] args)
{
using(var dbContext=new AdventureWorksContextContainer())
{
var o = new Order();
o.OrderDate = DateTime.Now;
ctx.Orders.Add(o);
ctx.SaveChanges(); var orders = from od in dbContext.Orders
select od; foreach (Order order2 in orders)
{
Console.WriteLine("OrderID:{0},OrderDate:{1}",order2.Id,order2.OrderDate);
} Console.Read();
}
}
}
}
查询结果:

![]() |
注意:如果我们的模型发生改变,只需要在模型设计视图修改模型,让后保存此时实体类就会相应改变,然后选择“从模型生成到数据库”重新执行生成的脚本即可。 |
Code First
Code First模式我们称之为“代码优先”模式,是从EF4.1开始新建加入的功能。使用Code First模式进行EF开发时开发人员只需要编写对应的数据类(其实就是领域模型的实现过程),然后自动生成数据库。这样设计的好处在于我们可以针对概念模型进行所有数据操作而不必关系数据的存储关系,使我们可以更加自然的采用面向对象的方式进行面向数据的应用程序开发。
从某种角度来看,其实“Code First”和“Model First”区别并不是太明显,只是它不借助于实体数据模型设计器,而是直接通过编码(数据类)方式设计实体模型(这也是为什么最开始“Code First”被叫做“Code Only”的原因)。但是对于EF它的处理过程有所差别,例如我们使用Code First就不再需要EDM文件,所有的映射通过“数据注释”和“fluent API”进行映射和配置。另外需要注意的是“Code First”并不代表一定就必须通过数据类来定义模型,事实上也可以通过现有数据库生成数据类。
那么我们首先看一下传统的Code First如何使用。
首先创建一个控制台应用程序,接下来添加两个类“Order”和“OrderDetail”,我们可以看到这两个类只是简单的C#对象(POCO,Plain Old C# Object)这两个类基本和EF没有任何关系,需要注意的是这两个类有两个导航属性“Order.OrderDetails”和“OrderDetail.Order”:
using System;
using System.Collections.Generic; namespace CodeFirst
{
public class Order
{
public int Id { get; set; }
public string Customer { get; set; }
public System.DateTime OrderDate { get; set; } public virtual List<OrderDetail> OrderDetails { get; set; }
}
}
using System;
using System.Collections.Generic; namespace CodeFirst
{
public partial class OrderDetail
{
public int Id { get; set; }
public string Product { get; set; }
public string UnitPrice { get; set; }
public int OrderId { get; set; } public virtual Order Order { get; set; }
}
}
有了这两个类之后让我们定义一个数据库上下文,有了它我们就可以对数据进行增删改查操作了,这个类必须继承于"System.Data.Entity.DbContext”类以赋予它数据操作能力。因此接下来我们需要给这个应用安装EntityFramework包,因为到目前为止我们并没有引入EF框架相关的任何内容,我们需要引入EF相关程序集。但是我们有更好的选择那就是NuGet。通过NuGet进行在线安装:项目中右键选择"Manage NuGet Packages…”;选择Online;再选择“EntityFramework”;然后点击安装即可。不了解NuGet的朋友到这里看一下使用 NuGet 管理项目库。数据库上下文操作类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity; namespace CodeFirst
{
public class OrderContext:DbContext
{ public DbSet<Order> Orders
{
get;
set;
} public DbSet<OrderDetail> OrderDetails
{
get;
set;
}
}
}
然后我们进行测试,在这个类中我们首先创建了一个Order实例,接着编码查询:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace CodeFirst
{
class Program
{
static void Main(string[] args)
{
using (var ctx = new OrderContext())
{ var o = new Order();
o.OrderDate = DateTime.Now;
ctx.Orders.Add(o);
ctx.SaveChanges(); var query = from order in ctx.Orders
select order;
foreach (var q in query)
{
Console.WriteLine("OrderId:{0},OrderDate:{1}", q.Id, q.OrderDate);
} Console.Read();
}
}
}
}
查询结果如图:

如果是第一次使用EF Code First的朋友一定会有疑问,我们没有进行任何数据库配置,增加了一条数据通过查询确实保存上了,那么我们的数据到底在哪呢?事实上如果用户不进行数据库配置EF默认会使用“.\SQLEXPRESS”数据库实例,如果你没有安装“.\SQLEXPRESS”则默认使用LocalDb,关于LocalDb的具体细节请看:SQL Server 2012 Express LocalDB,例如我本机就存放在:“C:\Users\Kenshin”,可以看到创建了一个名为“CodeFirst.OrderContext”的数据库:

但是多数情况下我们是希望自己控制这个数据库的,例如我想让他保存在我机器上的”.\SQL2008”实例上,此时我们就需要在配置文件App.Config中配置一个数据库连接串,然后在我们的数据库上下文中指定这个连接名称。
配置文件:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="CodeFirstDb" connectionString="Data Source=.\SQL2008;Database=CodeFirstDb;UID=sa;PWD=123;" providerName="System.Data.SqlClient"></add>
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
</configuration>
OrderContext类,构造函数多了一个连接名参数:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity; namespace CodeFirst
{
public class OrderContext:DbContext
{
public OrderContext(string connectionName)
: base(connectionName)
{
} public DbSet<Order> Orders
{
get;
set;
} public DbSet<OrderDetail> OrderDetails
{
get;
set;
}
}
}
使用的时候,传入配置的数据库连接字符串名称:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace CodeFirst
{
class Program
{
static void Main(string[] args)
{
using (var ctx = new OrderContext("CodeFirstDb"))
{ var o = new Order();
o.OrderDate = DateTime.Now;
ctx.Orders.Add(o);
ctx.SaveChanges(); var query = from order in ctx.Orders
select order;
foreach (var q in query)
{
Console.WriteLine("OrderId:{0},OrderDate:{1}", q.Id, q.OrderDate);
} Console.Read();
}
}
}
}
执行之后就会发现在”.\SQL2008”实例上多了一个“CodeFirstDb”数据库(注意图中除了我们创建的两个实体表还有一个系统表dbo._MigrationHistory它记录了模型的定义,在以后的文章中我会着重解释此表):

到了这里我们三种EF编程方式已经全部介绍完了,关于Code First模式如何更新模型、如何先建数据库再生成数据类以及更多EF问题在接下来的文章中再探讨。
EntityFramework5学习的更多相关文章
- EntityFramework5.0CodeFirst全面学习
Code First 约定 借助 CodeFirst,可通过使用 C# 或Visual Basic .NET 类来描述模型.模型的基本形状可通过约定来检测.约定是规则集,用于在使用 Code Firs ...
- ASP.NET MVC4+EasyUI+EntityFrameWork5权限管理系统——菜单模块的实现(二)
ASP.NET MVC4+EasyUI+EntityFrameWork5权限管理系统——数据库的设计(一) 菜单和模块是在同一个表中,采用的是树形结构,模块菜单表结构如下代码: USE [Permis ...
- VS2010安装EntityFramework5.0
EntityFramework 当前最新版本是6.0,2012年10月份发布,不过是alpha1版本,稳定版本是8月份发布的5.0版本,对于初学者来说,还是别在测试版上折腾了,先学习稳定的5.0版本, ...
- EntityFramework5提供的迁移工具
目录 背景之前是如何做的?EntityFramework5提供了更好的选择备注 背景返回目录 刚毕业做项目的时候,没有用“迁移”这个概念,系统发布和更新的过程让人非常痛苦,在学习 Ruby On Ra ...
- 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代
2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...
- Angular2学习笔记(1)
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- 消息队列——RabbitMQ学习笔记
消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
随机推荐
- U3D中IOS平台泛型方法尽少使用
U3D的IOS最小运行库use micro mscorlib是不包含泛型反射方法的,如FieldType.GetGenericArguments方法.所以尽量少用List而直接使用array. 另外请 ...
- UML3
在UML系统开发中有三个主要的模型: 功能模型: 从用户的角度展示系统的功能,包括用例图. 对象模型: 采用对象,属性,操作,关联等概念展示系统的结构和基础,包括类图. 动态模型: 展现系统的内部行为 ...
- 安卓开发笔记——重识Activity
Activity并不是什么新鲜的东西,老生常谈,这里只是随笔记录一些笔记. 每当说起Activity,感觉最关注的还是它的生命周期,因为要使我们的应用程序更加健壮,客户体验更加良好,如果对生命周期不熟 ...
- javacc学习
为什么要研究这些,除了个人兴趣之外,还有可以了解语言是怎样解析字符串生成逻辑代码. 他的应用性也是非常之广,如人工智能方面,把复杂的逻辑抽象成简单的文法,不懂编程的人都可以使用 说到人工智能,数据库S ...
- 【转载】linux内核启动android文件系统过程分析
主要介绍linux 内核启动过程以及挂载android 根文件系统的过程,以及介绍android 源代码中文件系统部分的浅析. 主要源代码目录介绍Makefile (全局的Makefile)bioni ...
- PE渲染引擎 一
PE是我业余时间做的一个纯dx11的渲染框架.主要就是练手.如果有时间,会把它“扩展”成真正的引擎(标配至少要有个对应的编辑器吧 -_!!). 目前实现的有: obj文件加载,binormal计算. ...
- 各种Camera,总有一款适合你(一)
根据游戏类型的不一样,会需要各种各样的摄像机,下面将分享三种典型的摄像机类型:(1)地下城摄像机:(2)第三人称跟随摄像机:(3)鼠标控制旋转摄像机.将这些控制脚本拖动到场景的MainCamera上即 ...
- Tools - 为知笔记
为知笔记 Homepage Web登陆 帮助支持 功能 特色功能 发布到blog 便携版制作 模板 如何建立模板 下载为知笔记模版 Markdown http://www.wiz.cn/markdow ...
- sqlite3存储格式
本篇介绍sqlite3数据库文件的存储格式.通过阅读源读源代码可以知道sqlite的设计思想.一个sqlite数据库文件对应着一个数据库.sqlite将数据库文件划分大小一致的存储(以区分内存)页面, ...
- CentOS6.5菜鸟之旅:VirtualBox4.3识别USB设备
一.前言 VirtualBox默认是不能识别USB设备的,但可以通过Oracle VM VirtualBox Extension Pack来增强VirtualBox的功能,增强的功能如下: 1. US ...
