EF实体框架添加Oracle的存储过程,得到结果集
最近在做项目时,需要在Oracle中创建一个存储过程,同时该存储过程返回一个数据集。大部分都遇到了“The selected stored procedure or function returns no columns” 的问题。该文章旨在解决此问题。
数据描述
在这里,我创建了三张表,分别为TAbelA, TableB , TabelC ,这三张表没有任何业务含义,仅为了测试试用。
CREATE TABLE TABLEA(
TABLEA_NO NUMBER PRIMARY KEY ,
TABLE_NAME VARCHAR2(32) NOT NULL ,
PHONE VARCHAR(32) NOT NULL
);
CREATE TABLE TABLEB(
TABLEB_NO NUMBER PRIMARY KEY ,
TABLE_NAME VARCHAR(32) NOT NULL ,
ADDRESS VARCHAR(32) NOT NULL
);
CREATE TABLE TABLEC(
TABLEC_NO NUMBER PRIMARY KEY ,
TABLE_NAME VARCHAR(32) NOT NULL,
EMAIL VARCHAR(32) NOT NULL
);
INSERT INTO JHQ.TABLEA(TABLEA_NO,TABLE_NAME,PHONE)VALUES(1,'TABLE_A' , 'PHONE_100');
INSERT INTO JHQ.TABLEA(TABLEA_NO,TABLE_NAME,PHONE)VALUES(2,'TABLE_A' , 'PHONE_101');
INSERT INTO JHQ.TABLEB(TABLEB_NO,TABLE_NAME,ADDRESS)VALUES(1,'TABLE_B' , 'ADDRESS_100');
INSERT INTO JHQ.TABLEB(TABLEB_NO,TABLE_NAME,ADDRESS)VALUES(2,'TABLE_B' , 'ADDRESS_101');
INSERT INTO JHQ.TABLEC(TABLEC_NO,TABLE_NAME,EMAIL)VALUES(1,'TABLE_C' , 'EMAIL_100');
INSERT INTO JHQ.TABLEC(TABLEC_NO,TABLE_NAME,EMAIL)VALUES(2,'TABLE_C' , 'EMAIL_101');
--该存储过程获取单个表的数据
CREATE OR REPLACE PROCEDURE SP_GET_SINGLE_TABLE(tablename in VARCHAR, RES OUT SYS_REFCURSOR)
IS
BEGIN
DBMS_OUTPUT.put_line(tablename);
OPEN RES FOR SELECT * FROM JHQ.TABLEA ;
END ;
--该存储过程获取多个表的数据
CREATE OR REPLACE PROCEDURE SP_GET_MULTIPLE_TABLES(tablename in VARCHAR, RES_A OUT SYS_REFCURSOR, RES_B OUT SYS_REFCURSOR, RES_C OUT SYS_REFCURSOR) IS
BEGIN
DBMS_OUTPUT.put_line(tablename);
OPEN RES_A FOR SELECT * FROM JHQ.TABLEA ;
OPEN RES_B FOR SELECT * FROM JHQ.TABLEB ;
OPEN RES_C FOR SELECT * FROM JHQ.TABLEC ;
END;
CREATE OR REPLACE PROCEDURE SP_GET_TABLEB(tablename in VARCHAR, RES OUT SYS_REFCURSOR)
IS
BEGIN
DBMS_OUTPUT.put_line(tablename);
OPEN RES FOR SELECT * FROM JHQ.TABLEB ;
END ;
CREATE OR REPLACE PROCEDURE SP_GET_TABLEC(tablename in VARCHAR, RES OUT SYS_REFCURSOR)
IS
BEGIN
DBMS_OUTPUT.put_line(tablename);
OPEN RES FOR SELECT * FROM JHQ.TABLEC ;
END ;
目前数据库部分已经创建好了,现在的要做的就是,从存储过程SP_GET_SINGLE_TABLE和储存过程SP_GET_MULTIPLE_TABLES来获取数据。
环境要求
1、ODTwithODAC122010 官方下载地址该组件必须安装
2、VS2017
创建项目
1、创建控制应用程序,.NetFramework 4.5,这一步不做介绍
2、选择“view” Sever Explorer ,如图 3.1
3、点击图3.2中的连接数据库按钮
4、点击“Change…”按钮,选择数据源,如图:3.3
5、选择数据源和数据驱动,如图3.4所示,在这里只说明Oracel的使用方式,其他不做介绍。
数据源选择Oracle,数据驱动选择ODP.NET Managed Driver .(这里安装ODTwithODAC之后才有).注意:这里一定要选择ODP.NET,因为在接下来的操作中,需用使用这个驱动生成配置数据 ,选择好之后,点击“OK”。
6、填写用户名,密码,选择自己的数据库,编辑连接名称,点击“测试连接”,提示“连接成功”之后,点击“确定”即可,如图3.5。
6、添加edmx,如图3.6,3.7,3.8,3.9,3.10,3.11。
至此数据模型已完成。
7、生成配置文件,这一步很重要。打开第三步中连接的数据库,依次选择图中标记的,如图3.12所示。
8、点击“Run”之后,输入所需的参数,如图3.13所示。点击“OK” , 我这里的参数没有任何业务意义,只是为了演示需要,大家根据自己实际需求填写,一定要保存该存储过程能正常运行。
9、在该界面,如图3.14所示。可以点击“Click here for details” 来查看存储过程获取的结果集,勾选“Selecte for config” ,点击“Show Config” 会加载出该结果集字段的映射。点击“Add Config” 将该配置信息加载到“App.Config”里面。
我这里的配置信息如下,7、8、9这三步很重要,切记不可忽略
<oracle.manageddataaccess.client>
<version number="*">
<implicitRefCursor>
<storedProcedure schema="JHQ" name="SP_GET_SINGLE_TABLE">
<refCursor name="RES">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEA_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="PHONE" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
</storedProcedure>
</implicitRefCursor>
</version>
</oracle.manageddataaccess.client>
10、在edmx空白处,右击,选择“模型预览”,如图 3.15
8、选择自己要用的的存储过程, “右击”选择“添加函数导入”,如图3.16
11、填写函数名称 ,选择“Complex” , 依次点击“Get Column Inforomation” ,“Create New Complex_Type” ,点击“OK” 。图 3.16
12、此时,在Function Imports 中,就会有个FUNC_SP_GET_SINGLE_TABLE的函数。如图3.17
13、获取数据
4 获取多个结果集
1、参考上一节中的7,8,9,10。用相同的方法,添加SP_GET_MULTIPLE_TABLES,SP_GET_TABLEB,SP_GET_TABLEC这三个存储过程。其中SP_GET_TABLEB,SP_GET_TABLEC这两个存储过程仅仅是为了生成数据模型。在SP_GET_MULTIPLE_TABLES存储过程中,虽然有三个输出参数,但是在生成模型的时候,它是会生成默认的第一个。这也就是为什么写SP_GET_TABLEB,SP_GET_TABLEC这两个存储过程的原因。
<storedProcedure schema="JHQ" name="SP_GET_MULTIPLE_TABLES">
<refCursor name="RES_A">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEA_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="PHONE" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
<refCursor name="RES_B">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEB_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="ADDRESS" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
<refCursor name="RES_C">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEC_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="EMAIL" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
</storedProcedure>
<storedProcedure schema="JHQ" name="SP_GET_TABLEB">
<refCursor name="RES">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEB_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="ADDRESS" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
</storedProcedure>
<storedProcedure schema="JHQ" name="SP_GET_TABLEC">
<refCursor name="RES">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="TABLEC_NO" providerType="Decimal" allowDBNull="false" nativeDataType="Number" />
<metadata columnOrdinal="1" columnName="TABLE_NAME" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
<metadata columnOrdinal="2" columnName="EMAIL" providerType="Varchar2" allowDBNull="false" nativeDataType="Varchar2" />
</refCursor>
</storedProcedure>
2、参考上节的11,12这两步,分别导入FUNC_SP_GET_MULTIPLE_TABLES,FUNC_SP_GET_TABLEB,FUNC_SP_GET_TABLEC。如图4.1所示。
3、选中edmx,右击,选择“open with" ,在弹窗里选择”Automatic Editor Selector“ ,点击”OK".
4、修改返回类型,手动修改XML内容,让其返回多个集合,图4.3为修改前,图4.4为修改后。
5、修改返回数据集的字段映射,图4.5为修改前,图4.6为修改后。注意,在这里做映射的时候,映射的顺序要和上一步返回的类型保持一直。
6、获取结果集,如图4.7
备注
demo下载
在手动修改之后,vs设计器会报异常,如下图所示,不过不影响使用。