Entity Framework 5.0系列之EF概览_entity framework 5.0教程-程序员宅基地

技术标签: Entity Framework  ASP.NET MVC  

概述

在开发面向数据的软件时我们常常为了解决业务问题实体、关系和逻辑构建模型而费尽心机,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问题在接下来的文章中再探讨。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xingxing513234072/article/details/13294011

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法