一、前言
1、Entity Framework是什么?
Entity Framework是微软对ORM框架的实现。类似的实现也有其它方式,如DevExpress 的XPO(eXpress Persistant Object,非微软公司的产品),都是比较有名的。如果时间来得及,后续会比较这两个产品。下文简称EF。
2、为什么要用ORM
有数据库编程经验的人应该知道,程序中的对象模型很大程度来源于数据库中的表,且有较强的对应关系(很多时候就是一个对应一个表)。建立这种对应关系,传统的作法是:先在数据库中建表T,再在程序中编写类C,类中的属性逐个对应表中的字段。系统运行时,数据操作层从数据库中取出表记录r,一条记录去生成一个类对象o...
以上的种种过程总结起来就是:表和对象的相互关联与转化。
这里存在大量的机械化工作,是否可以由某种机制去代替这些太繁琐的工作呢?有,这就是ORM存在的意义之一。除了效率外其它的好处还有:规范、简洁、易维护...
3、在开始前,还有几个重要概念,你必须要清楚。Code Frist?Database First?Model First?
这其实是编码的几种方式,理解起来也不复杂,基本上可以按照字面意思来理解。
Database First:如果数据库表对象已经存在,EF 可以根据数据库中的表及字段,建立POCO(Plain Old CLR Object,简单理解为‘简单类’,即没有方法,仅有attribute和property的类)对象。简言之,先有(更新)数据库,再有(更新)类/对象
Model First :先建议Model,EF根据Model生成数据库。
Code First:这种方式在MVC模式中非常流行,对于数据库对象的修改完全通过代码,而非手工去操作数据库。本文中未使用这种方式,后续文章单独讲解。
具体差别,在下文中体会吧。
4、目的:本文包括如何使用EF、LINQ以及使用Model-First方式生成数据库对象定义脚本。涉及Oracle数据库、VisualStudio、ODP.NET。先从已有数据库中,通过 Entity Data Model Wizard (studio中的向导)创建实体数据模型Entity Data Model (EDM),并通过三种方式来查询EDM:
a、Linq ; b、含Lamda 表达式的 Linq ; c、Entity SQL
5、环境准备
a、VisualStudio 2013 和.net framework 4.5以上
b、Oracle 11g release 2 以上
c、ODAC 12c Release 3 (12.1.0.2.1) 以上,可从Oracle官网下载。ODAC中含有为visual studio准备的开发者工具插件、ODT组件,这些在你安装ODAC时就都有了。
d、本文中的数据库HR,是Oracle的示例数据库之一(除此之外还有OE、PM、IX、SH),Oracle官方的很多示例程序都基于此数据库,建议安装。可以从你的oracle安装文件中找到($ORACLE_HOME/demo/schema),Oracle官网有,读者也可自行百度,有问题可留言。如果你英文OK,也可直接浏览 https://docs.oracle.com/database/121/COMSC/installation.htm#COMSC001
e、这些文件files.zip下载备用(注意下载链接)
二、准备工作
1、创建一个名称为EntityFramework 的控制台应用程序
2、创建实体数据模型Entity Data Model前,要用ODT创建Oracle连接
a、在Server Explorer中添加连接
b、注意,这里要用ODP.NET Managed 驱动,如图
c、输入你的数据库连接信息,确保数据库可以正常连接。
d、打开query window,复制以下脚本并执行。
e、在下载文件中找到三个存储过程脚本文件:INCREASE_SALARY_BY_10, UPDATE_AND_RETURN_SALARY 和 OUTPARAM,拷到Query Window 中执行。确保新添加的存储过程出现在Procedure节点中
三、使用向导创建EDM
a、在项目上点击右键,选择‘Add New Item’
b、在向导中选择‘EF Designer from Database’,并选择下一步
c、注意选择数据库连接,选中保存敏感信息(数据库密码),并将连接设置保存在app.config中,如图:
d、注意选择表对象: DEPARTMENTS 和 EMPLOYEES ,三个存储过程对象: INCREASE_SALARY_BY_10 , UPDATE_AND_RETURN_SALARY 以及 OUTPARAM
四、三种方式进行EDM查询
1、使用LINQ查询
a、添加 System.Data.Entity 引用
b、在Program.cs文件中,编写如下代码
e、编译执行结果如下:
注意,如果系统编译错误、数据连接错误,请按如下步骤检查
a、如果出现错误:Error 66 Argument 10: cannot convert from 'System.Data.Objects.ObjectParameter' to 'System.Data.Entity.Core.Objects.ObjectParameter' D:\Aziz\Aziz Project\Development\Running Development\Web\pos\pos\Model1.Context.cs 351 278 pos
问题产生的原因:你使用了Entity Framework 6
解决办法是:在context.cs文件中,修改命名空间,如下图:
以上问题,如果使用Entity Framework 5则不会出现
b、如果出现数据连接错误,则修改app.config如下:
在entityFramework配置节中,修改provider配置
<providers>
<!--<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />-->
<provider invariantName="Oracle.ManagedDataAccess.Client"
type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
</providers>
c、打开NuGet,为项目添加ODP.NET
2、通过 lambda 表达式和 存储过程映射执行LINQ查询
LINQ查询可含有Lambda表达式。Lambda表达式可作为LINQ各种标准查询方法的参数。通过将 Oracle 存储过程映射到 EDM 中的更新、插入和删除操作,可以对实体执行这些操作。
本部分将对 EMPLOYEE 实体执行一个使用 lambda 表达式的 LINQ 查询,然后映射一个存储过程以对所有选出的行执行更新操作。这将使用之前导入到 EDM 中的一个存储过程。
a、首先,需要创建要更新的数据对象与存储过程的映射(mapping)关系。当.NET要试图更新数据时,映射的存储过程会对LINQ选出的数据行进行更行。打开HRModel.edmx,并打开Model Browser.
b、在 HRModel.edmx 中,右键单击 EMPLOYEES 实体并选择 Stored Procedure Mapping
c、在 Mapping Details - EMPLOYEE 窗口中,选择 <Select Update Function>,然后选择 INCREASE_SALARY_BY_10 存储过程。
d、在实体和 Oracle 数据库之间建立参数数据类型映射。从下拉列表中选择 EMPLOYEE_ID 作为 ID,选择 SALARY 作为 SAL
e、键入下图中高亮显示的代码,或在 Programcs.txt 中复制以 LINQ using lambda expressions -- 开头的代码块,然后粘贴到 Program.cs 中已有代码语句的后面。单击 (启动调试)
在应用程序中,注意到 result.SALARY 设置为 18000。实际上,Entity Framework 执行的存储过程将工资增加了 10。在下一部分中,您将对这些行执行查询,以证明工资的确增加了 10。其实,实现了类似传统意义上的数据库触发器的效果。
注:在查看了第一个结果集之后,按 Enter 键继续。
3、执行Entity SQL 查询
在本部分中,将查询与前一部分相同的行,来证明存储过程已成功更新这些行。将使用 Entity Framework 中的另一种查询方法 Entity SQL 进行查询。
键入下图中高亮显示的代码,或在 Programcs.txt 中复制以 Entity SQL -- 开头的代码块,然后粘贴到 Program.cs 中已有代码语句的后面。单击 (启动调试),查看工资增加 10 的更新结果。
注:查看输出之后,按两下 Enter 继续。
五、函数导入和隐式结果集检索 | 直接插入和更新数据
通过 Entity Framework,开发人员能够定义自己的 .NET 方法来执行数据库存储过程。具体做法是在概念模型中创建函数导入,并将其映射到存储过程。本部分将定义自己的方法并映射到 Oracle 存储过程,用以执行更新。该存储过程还将使用一个隐式结果集返回修改后的数据。开发人员在 .NET 配置文件中定义结果集元数据,以便 Entity Framework 正确检索数据。
本部分介绍如何在 Entity Framework 中以编程方式修改 Oracle 数据库数据。并将对 DEPARTMENTS 表执行插入和删除操作。
1、您将使用 Visual Studio 的函数导入工具将存储过程映射到用户定义的 .NET 方法。由于存储过程返回一个隐式结果集,因此在使用该工具之前,需要通过向导在 .NET 配置文件中定义结果集元数据。在Server Explorer中找到存储过程 UPDATE_AND_RETURN_SALARY ,右键,选择 RUN .
2、打开Run Procedure 窗口。界面参数保持默认,不做修改。
3、存储过程执行成功。在Out Parameters中,为New_SALARY选中‘Select For Config’
4、点‘Show Config’,预览出即将要添加到App.config中的配置信息,包括返回数据集、列等元数据信息;点‘AddConfig’按钮,则将预览窗口的信息添加到App.config中。
5、App.config中添加上了refCursor信息
6、接下来,将使用函数导入工具把一个 .NET 方法映射到 Oracle 存储过程。右键单击 HRModel.edmx 并选择 Model Browser。
7、在 Model Browser 中,依次展开 HRModel.Store 和 Stored Procedures 节点。选择 UPDATE_AND_RETURN_SALARY 存储过程。之前在创建 EDM 时导入了该存储过程
8、右键单击 UPDATE_AND_RETURN_SALARY 并选择 Add Function Import。
6、在 Add Function Import 窗口中,选择 Returns a Collection Of 部分中的 Complex。存储过程所返回的结果集中仅包含两列,而不是完整定义的实体或标量值。
单击 Get Column Information。将从 .NET 配置文件中检索列信息。
7、依次点击Create New Complex Type 和 OK 按钮
在程序中将使用默认的 UPDATE_AND_RETURN_SALARY 函数名来调用此方法
8、在Program.cs文件中输入如下代码。注意,上下文件Context中已经有UPDATE_AND_RETURN_SALARY 这个方法了,调用此方法将调用映射的存储过程,并返回数据集。
9、运行程序,显示人员姓名和更改后的薪资。
六、从存储过程中获传出型参数值
本部分验证如何从存储过程中获取output 型的参数值。传出型的参数只需要在.Net中显式声名并映射到存储过程的Output Parameter。这不同于以往的EF版本中的使用导入函数的方式来获取传出参数。
1、打开Program.cs文件,键入如下代码。注意,entity context 拥有方法 OUTPARAM。ObjectParameter 对象被作为OUTPARAM方法的参数,与方法的传出型参数绑定。
程序运行结果如下:
七、使用LINQ进行数据插入、删除操作
本部分论证如何以编码方式使用LINQ进行插入、删除等操作
1、在Program.cs中键入如下代码。注释已说明了每段代码的操作
2、运行结果如下:
八、Model-First
本部分将在EMPLOYEE实体添加一个属性。为了能在数据库表中添加上相应列,Visual Studio将生成Oracle 的DDL脚本。这些脚本能够在Oracle 数据库中运行并更新表。
1、在HRModel.edm中,为EMPLOYEE实体添加新属性,名称为ADDRESS
2、在模型浏览窗口右键点击Model,选择Properties,做如下更改:将属性Database Schema Name 改为 HR ,将属性DDL Generation Template 设为SSDLtoOracle.tt (VS) ,将属性Database Generation Workflow 设为Generate Oracle via T4(TPT).xaml (VS)
3、右键 HRModel.edmx 选择 Generate Database from Model 菜单项
4、接下来的弹出窗口中点OK
5、数据库向导生成了DDL脚本,这些脚本可单独保存成文件,单独运行。注意:脚本能够创建和删除数据库对象。默认地,删除脚本被注释掉了。如果你想使用,可以执行前取消注释。
九、总结
本文涉及如下内容:
1、创建Oracle Connection
2、使用向导创建实体数据模型Entity Dtata Model
3、三种方式检索查询Entity Framework Data
4、映射存储过程到EDMs
5、使用函数导入功能( Entity Framework Function Imports )创建与存储过程映射的函数
6、存储过程的传出参数的检索方法
7、编码方式修改Entity Framework data
8、以Model-First方式生成DDL脚本,并修改数据库对象