Model First
Model First我们称之为“模型优先”,这里的模型指的是“ADO.NET Entity Framework Data Model”,此时你的应用并没有设计相关数据库,在Visual Studio中我们通过设计对于的数据模型来生成数据库和数据类。
首先创建一个控制台应用程序,右键添加新建项,选择“ADO.NET Entity Data Model”,名称输入EFDemoDB(此名称跟上一个没有任何联系,只是重名而已):
在模型设计视图中,添加新实体:(空白处右键)
添加,两个Scalar属性:“Customer”和“OrderDate(为datetime类型,可选中它在属性中修改)”;同样的方式添加第二个实体“OrderDetail”,并添加“Product”和“UnitPrice”属性:
接下来我们添加二者之间的关系,“Order”和“OrderDetail”是一对多的关系,“Order”可以通过“OrderDetails”属性访问“OrderDetail”实体,“OrderDetail”可以通过“Order”属性访问“Order”实体,并且添加了一个外键约束到“OrderDetail”中:
添加过关系后:
到目前为止Model First中的Model已经创建结束,下面就需要生成到数据库了,在模型设计视图空白处选择“从模型生成到数据库…”:(这里还是用的上面那个EFDemo数据库,可根据自己需求更改,新建连接更换数据库)
选择数据库连接,点击下一步,你将会看到生成的sql语句:
点击完成,不出意外的话将打开生成的脚本,当然你也可能会出现如下错误,请下载最新的SQL Server Data Tool(本地VS2012,数据库SQLServer2008R2出现了下面的提示,下载更新即可,建议直接下载镜像文件):
在模型保存后,生成了数据库上下文和实体类,并且打开了建表的脚本:
说明:如果没有,看看模型是否保存了(如下图)
打开的数据库脚本:
然后右键选择执行即可。
然后编码查询一下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.ComponentModel; 5 using System.Data; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace EFDemo 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Order o = new Order() { Customer = "", OrderDate = DateTime.Now }; EFDemoDBContainer db = new EFDemoDBContainer(); 16 db.Orders.Add(o); 17 int result = db.SaveChanges(); 18 19 var orders = from od in db.Orders select od; 20 21 foreach (Order order2 in orders) 22 { 23 Console.WriteLine("OrderID:{0},OrderDate:{1}", order2.Id, order2.OrderDate); 24 } 25 26 Console.Read(); 27 } 28 } 29 }
运行结果(正常情况下应该只有一行,这是我多次运行后的结果):
注意:如果我们的模型发生改变,只需要在模型设计视图修改模型,让后保存此时实体类就会相应改变,然后选择“从模型生成到数据库”重新执行生成的脚本即可。
Database First
“Database First”模式我们称之为“数据库优先”,前提是你的应用已经有相应的数据库,你可以使用EF设计工具根据数据库生成数据数据类,你可以使用Visual Studio模型设计器修改这些模型之间对应关系。
首先创建一个控制台应用程序,然后右键添加新建项,选择“ADO.NET Entity Data Model”,名称输入EFDemoDB:
接着选择从数据库生成:
下一步选择数据库连接,选择我们刚刚建的EFDemo数据库。
下拉框里没有,我们点击新建连接
然后选择表
创建完模型之后
你会发现Visual Studio自动为你生成了“Class、“Student”两个实体类和一个“EFDemoDB”数据库上下文操作类:
下面简单的看一下如何使用EF进行数据查询,通过下面的代码我们可以看到EF对于数据的操作入多么优雅:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace EFDemo 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 EFDemoEntities db = new EFDemoEntities(); 14 15 //按照ID排序,并查找 16 var model = db.Classes.OrderBy(m => m.ID).Select(m => new 17 { 18 ID = m.ID, 19 Name = m.Name 20 }); 21 22 23 if(model.Count() > 0) 24 { 25 Console.WriteLine("ID号:{0}", model.First().ID); 26 Console.WriteLine("班级名:{0}", model.First().Name); 27 } 28 } 29 } 30 }
运行结果:
注意:如果你的数据库表结构发生改变后,只需在模型设计视图空白处右键,选择“从数据库更新模型”接着按照向导操作即可。(如下图)
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; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DemoEF { 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; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DemoEF { 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”;然后点击安装即可。
数据库上下文操作类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DemoEF { 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。我们可以在这里找到系统自动创建的数据库:
但是多数情况下我们是希望自己控制这个数据库的,例如我想让他保存在我机器上的”.\SQL2008”实例上,此时我们就需要在配置文件App.Config中配置一个数据库连接串,然后在我们的数据库上下文中指定这个连接名称。
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=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <connectionStrings> <add name="CodeFirstDb" connectionString="Data Source=LENOVO\SQLEXPRESS;Database=CodeFirstDb;UID=sa;PWD=sql;" providerName="System.Data.SqlClient"></add> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> </configuration>
OrderContext类,构造函数多了一个连接名参数:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity; namespace DemoEF { 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; using System.Threading.Tasks; namespace DemoEF { 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(); } } } }
执行之后就会发现在”.\sqlexpress”实例上多了一个“CodeFirstDb”数据库(注意图中除了我们创建的两个实体表还有一个系统表dbo._MigrationHistory它记录了模型的定义,在以后的文章中我会着重解释此表):
到了这里我们三种EF编程方式已经全部介绍完了。
本文出自http://www.cnblogs.com/zrdm/
由笔者进行整理,如果涉及隐私,请留言,立马删除。
如有冒犯,请多包涵。