深入浅出EF之ModelFirst和DBFirst

来源:互联网 发布:手机书生软件 编辑:程序博客网 时间:2024/05/16 08:33

        在上篇博文中,小编主要简单的介绍了一下EF的一些基础知识,其中,小编蜻蜓点水的提了一下ModelFirst和DBFirst,ModelFirst先设计实体,然后根据模型生成数据库,DBFirst根据数据库生成模型,两个方向都是可以了,两个方向可以相互更新,比如新添加了实体,可以根据模型生成数据库,如果在数据库里面新添加了字段,我们可以从数据库更新模型。在介绍ModelFirst和DBFirst之前,我们先来解决两个问题,EF与linq to sql的关系以及为什么使用linq to sql和EF。

         EF与linq to sql的关系

         linq  to sql 是微软ORM思想的一个具体化,EF也是它的一个具体化,那么,这两个产品有什么区别呢?Linq to Sql是ORM思想实现的一个轻量级的框架,EF是一个重量级框架;Linq to Sql和EF的一个重要的区别就是,Linq to Sql只能针对于SQL Server数据库,而EF可以针对于很多的数据库(Oracle,SQL Server等),也就是说EF是跨数据库的,不要小看这一点,在实际的开发中,非常的实用,举个简单的小例子,还记我们敲的VB.NET版本的机房收费系统么,其中涉及到了数据访问层,如果出于某种原因,我们换了数据库,那么,我们就需要重新编写数据访问层,如果我们在创机房收费系统这个项目的时候,使用了linq to sql,更换了数据库linq to sql框架就需要重新进行大量的改动,如果使用了EF框架,那么我们只需要改动其中的配置文件就可以了,不需要修改程序中的代码。

        为什么使用linq to sql和EF

        这个问题,也关乎我们的D层,还记得敲机房收费系统的时候,我们会抽出来一个sqlhelper类,这个类实现了对数据库的增删改查,然后,我们的再创建相应的D层类,这些类方法的功能,其实都差不多,唯一不同的就是sql,从这里我们可以看到,我们的D层的问题,那就是,我们重复性的书写一些不必要的类或者方法,解决这个方法就需要慢慢的抽象,抽象出共有的东西,像:DataTable装换为实体集,操作数据库的几类方法(注意其参数),然后将其一整合,这个大致就是我们所属的ORM思想实现的雏形了,当然,上面所说的那些东西,Linq to Sql或EF这些框架已经帮助我们实现了,我们只需要使用它们提供的方法就行了,从这里我们也可以看到,如果我们使用这些框架,我们程序员在编程的时候,几乎不需要管理D层的东西,只需要关注业务的实现就可以了。

        接下来,小编就来简单的介绍一下ModelFirst,ModelFirst先设计实体,然后根据模型生成数据库,如下图所示,

        

        我们可以再图中空白处右击添加实体,还可以新增标量属性,以及添加关联。接着,我们可以根据上面的实体生成数据库,如下图所示:

        

        生成的代码如下所示:

<span style="font-size:18px;"><span style="font-size:18px;">-- ---------------------------------------------------- Entity Designer DDL Script for SQL Server 2005, 2008, 2012 and Azure-- ---------------------------------------------------- Date Created: 01/28/2015 15:43:19-- Generated from EDMX file: C:\Users\Flower\Desktop\EFDemo\ModelFirstDemo\DataModel.edmx-- --------------------------------------------------SET QUOTED_IDENTIFIER OFF;GOUSE [ModelFirstDemoDb2];GOIF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');GO-- ---------------------------------------------------- Dropping existing FOREIGN KEY constraints-- --------------------------------------------------IF OBJECT_ID(N'[dbo].[FK_CustomerOrder]', 'F') IS NOT NULL    ALTER TABLE [dbo].[Order] DROP CONSTRAINT [FK_CustomerOrder];GO-- ---------------------------------------------------- Dropping existing tables-- --------------------------------------------------IF OBJECT_ID(N'[dbo].[Customer]', 'U') IS NOT NULL    DROP TABLE [dbo].[Customer];GOIF OBJECT_ID(N'[dbo].[Order]', 'U') IS NOT NULL    DROP TABLE [dbo].[Order];GO-- ---------------------------------------------------- Creating all tables-- ---------------------------------------------------- Creating table 'Customer'CREATE TABLE [dbo].[Customer] (    [Id] int IDENTITY(1,1) NOT NULL,    [CusName] nvarchar(32)  NULL,    [SubTime] datetime  NOT NULL,    [DelFlag] smallint  NULL);GO-- Creating table 'Order'CREATE TABLE [dbo].[Order] (    [Id] int IDENTITY(1,1) NOT NULL,    [OrderContent] nvarchar(max)  NOT NULL,    [CustomerId] int  NOT NULL);GO-- Creating table 'UserInfo'CREATE TABLE [dbo].[UserInfo] (    [Id] int IDENTITY(1,1) NOT NULL);GO-- ---------------------------------------------------- Creating all PRIMARY KEY constraints-- ---------------------------------------------------- Creating primary key on [Id] in table 'Customer'ALTER TABLE [dbo].[Customer]ADD CONSTRAINT [PK_Customer]    PRIMARY KEY CLUSTERED ([Id] ASC);GO-- Creating primary key on [Id] in table 'Order'ALTER TABLE [dbo].[Order]ADD CONSTRAINT [PK_Order]    PRIMARY KEY CLUSTERED ([Id] ASC);GO-- Creating primary key on [Id] in table 'UserInfo'ALTER TABLE [dbo].[UserInfo]ADD CONSTRAINT [PK_UserInfo]    PRIMARY KEY CLUSTERED ([Id] ASC);GO-- ---------------------------------------------------- Creating all FOREIGN KEY constraints-- ---------------------------------------------------- Creating foreign key on [CustomerId] in table 'Order'ALTER TABLE [dbo].[Order]ADD CONSTRAINT [FK_CustomerOrder]    FOREIGN KEY ([CustomerId])    REFERENCES [dbo].[Customer]        ([Id])    ON DELETE NO ACTION ON UPDATE NO ACTION;-- Creating non-clustered index for FOREIGN KEY 'FK_CustomerOrder'CREATE INDEX [IX_FK_CustomerOrder]ON [dbo].[Order]    ([CustomerId]);GO-- ---------------------------------------------------- Script has ended-- --------------------------------------------------</span></span>
        接着我们来看一个具体的例子,ModelFirst关联实体的插入操作代码如下所示:

<span style="font-size:18px;"><span style="font-size:18px;">using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ModelFirstDemo{    class Program    {        static void Main(string[] args)        {            DataModelContainer db = new DataModelContainer();            #region  Model First 关联实体的插入操作            Customer customer = new Customer();            customer.CusName = "呵呵";            customer.DelFlag = 0;            customer.SubTime = DateTime.Now;            Order order = new Order();            order.OrderContent = "Flower";            //给导航属性赋值            //order.CustomerID= customer.ID;            order.Customer = customer;            Order order2 = new Order();            order2.OrderContent= "Flower2";             order.CustomerID= customer.ID;            order2.Customer = customer;            db.Customer.Add(customer);            db.Order.Add(order);            db.Order.Add(order2);            db.SaveChanges();            #endregion        }    }}</span></span>
        接着,我们来看一下DBFirst,根据数据库生成模型,我们具体来看下面一段代码:

<span style="font-size:18px;"><span style="font-size:18px;">using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Data;    namespace EF.EntityFrameworkDemo  {      class Program      {          static void Main(string[] args)          {              #region 添加实体              ////创建上下文对象              //DBFirstEntities dbFirst = new DBFirstEntities();              ////操作实体                          //T_Customer customer = new T_Customer();              //customer.CusName = "新添用户";              ////附加在上下文              //dbFirst.T_Customer.AddObject(customer);              ////保存              //dbFirst.SaveChanges();              #endregion               #region 删除实体              ////1、创建上下文对象              //DBFirstEntities dbFirst = new DBFirstEntities();              ////2、创建实体              //T_Customer customer = new T_Customer();              //customer.ID = 9;              ////3、将实体附加到上下文里面来进行管理              //dbFirst.T_Customer.Attach(customer);              ////修改实体的状态              //dbFirst.ObjectStateManager.ChangeObjectState(customer, EntityState.Deleted);              ////4、上下文操作数据库              //dbFirst.SaveChanges();              #endregion               #region 修改实体              ////1、创建访问数据库的上下文对象              //DBFirstEntities dbFirst = new DBFirstEntities();              ////2、修改对象              //T_Customer customer = new T_Customer();              //customer.ID = 4;              //customer.CusName = "用户4_修改后2";              ////3、附加到数据库              //dbFirst.T_Customer.AddObject(customer);              ////修改对象状态              //dbFirst.ObjectStateManager.ChangeObjectState(customer, EntityState.Modified);              ////4、上下文更新数据库              //dbFirst.SaveChanges();              #endregion               #region 查询              DBFirstEntities dbFirst = new DBFirstEntities();                foreach (var item in dbFirst.T_Customer)              {                  Console.WriteLine(string.Format("ID:{0}  Name:{1}",item.ID,item.CusName));              }              #region linq表达式              T_Customer cs = (from customer in dbFirst.T_Customer where customer.ID == 2 select customer).SingleOrDefault();              Console.WriteLine("ID:{0}  Name:{1}",cs.ID,cs.CusName);              #endregion               #endregion                Console.ReadKey();          }      }  }  </span></span>

        ModelFirst和DBFirst两种方式,都可以达到我们想要的效果,实现同样的目的,两个方法可以相互更新,最后小编简单的来介绍一下延迟加载,延迟加载也可以叫做按需加载,可以分两方面来理解,一方面指暂时不需要该数据,不用在当前马上加载,而可以推迟到使用它时再加载;另一方面指不确定是否将会需要该数据,所以暂时请不要加载,待确定需要后再加载它。延迟加载是一种很重要的数据访问特性,可以有效地减少与数据源的交互(注意,这里所提的交互不是指交互次数,而是指交互的数据量),从而提升程序性能。在EF中有两种延迟加载,具体代码如下所示:

<span style="font-size:18px;"><span style="font-size:18px;">using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ModelFirstDemo{    class Program    {        static void Main(string[] args)        {            DataModelContainer db = new DataModelContainer();            #region  Model First 关联实体的插入操作            Customer customer = new Customer();            customer.CusName = "呵呵";            customer.DelFlag = 0;            customer.SubTime = DateTime.Now;            Order order = new Order();            order.OrderContent = "Flower";            //给导航属性赋值            order.CustomerID= customer.ID;            order.Customer = customer;            Order order2 = new Order();            order2.OrderContent= "Flower2";             order.CustomerID= customer.ID;            order2.Customer = customer;            db.Customer.Add(customer);            db.Order.Add(order);            db.Order.Add(order2);            db.SaveChanges();            #endregion            #region 补充另外一个汇总查询方式:Lambda表达式            Lambda表达式和linq表达式在编译阶段之后生成的IL代码是一样的            var item = (from c in db.Customer                        where c.Id == 2                        select c).FirstOrDefault();            List<string> list = new List<string>();            list.FindAll()            Function<Customer,bool>            lambda的方式            var itemLambda = db.Customer.Where<Customer>(c=>c.Id==1).FirstOrDefault();            Console.WriteLine(itemLambda.CusName);            #endregion            #region 延迟第一种            使用linq或者lambda表达式查出来的数据,只有使用的时候才回去真正的查询数据            var items = from c in db.Customer                        where c.Id < 10                        select c;            foreach (var customer in items)            {                Console.WriteLine(customer.Id);            }            IQueryable            foreach (var customer in items)            {                Console.WriteLine(customer.Id);            }            #endregion            #region 第二种延迟加载            var customers = from c in db.Customer                            select c;            foreach(var cus in customers)            {                Console.WriteLine(cus.Id + "------");                foreach (var order in cus.Order)                {                    Console.WriteLine(order.Id);                }                Console.WriteLine("------");            }            #endregion            #region 查询部分列的数据            只查询表中的部分列的数据            var items = from c in Customer                        where c.Id < 100                        select new { id = c.Id, CusName = c.CusName, count = 0, orderCount = c.Order.Count() };            foreach (var item in items)            {                Console.WriteLine(item.CusName + "------" + item.orderCount);            }            #endregion            #region IQuerable接口跟其他集合的区别            var items = (from c in db.Order                         where c.Id < 2                         select c).ToList();            foreach (var order in items)            {                Console.WriteLine(order.Id);            }            #endregion            Console.ReadKey();        }    }}</span></span>
       小编寄语:该博文,小编主要介绍了一些EF的基础知识,分别从三个大方面对EF进行详细介绍,第一个方面:EF与linq to sql的关系以及为什么要使用EF与linq  to sql,第二方面,介绍了一下ModelFirst和DBFirst,最后介绍了一下延迟加载,对于EF的相关知识,小编刚刚接触,理解的还是很浅,有不同意见的小伙伴可以一起讨论交流哦,常常想,如果不是因为缘分,如果不是因为接受了项目什么mvc、EF、linq等,小编也没有这么快就开始接触,在接项目的过程中学习,再把学习到的知识运用到项目中,赶脚棒棒哒,档案管理项目,未完待续......
2 1