无法在实体框架中映射 SYS_REFCURSOR

Posted

技术标签:

【中文标题】无法在实体框架中映射 SYS_REFCURSOR【英文标题】:Cant Map SYS_REFCURSOR in Entity Framework 【发布时间】:2013-02-19 09:41:37 【问题描述】:

我正在尝试通过实体框架访问 Oracle 11g 上的存储过程。我可以访问返回标量和返回正确值的存储过程。但是当使用 SYS_REFCURSOR 返回结果集时,函数导入时未检测到 OUT 参数

我的存储过程如下

create or replace PROCEDURE "GetAllClientNames" (
  "ID" IN NUMBER, 
  "SAL" IN NUMBER, 
  "EMP_CURSOR" OUT SYS_REFCURSOR) IS

BEGIN 


    OPEN EMP_CURSOR FOR SELECT FIRSTNAME FROM CLIENTS;

END;

但是在更新实体并进行函数导入时,在检索结果集的导入函数中未检测到 SYS_REFCURSOR OUT 参数。

请帮我解决这个问题。如果没有 OUT 参数,我无法访问存储过程检索到的结果集

【问题讨论】:

“导入”存储过程的流程是什么? @TomHalladay 存储过程必须作为函数导入,以便可以从实体框架中调用。 【参考方案1】:

可以使用实体框架从 Oracle 存储过程返回复杂类型,例如引用游标;它只需要一些额外的配置。您必须将正确的 XML 添加到配置文件中,以识别返回的 refcursor 和列的数据类型。

例子:

<oracle.dataaccess.client>
<settings>
  <add name="schema.storedproc.RefCursor.ref_cursor_param_name" value="implicitRefCursor bindinfo='mode=Output'" />
  <add name="schema.storedproc.RefCursorMetaData.OUT_REF_CUR.Column.0" value="implicitRefCursor metadata='ColumnName=<column_name_here>;BaseColumnName=<column_name_here>;NATIVEDATATYPE=Varchar2;ProviderType=Varchar2'" />
  <add name="schema.storedproc.RefCursorMetaData.OUT_REF_CUR.Column.1" value="implicitRefCursor metadata='ColumnName=<column_name_here>;NATIVEDATATYPE=Date;ProviderType=Date'" />
  <add name="schema.storedproc.RefCursorMetaData.OUT_REF_CUR.Column.2" value="implicitRefCursor metadata='ColumnName=<column_name_here>;NATIVEDATATYPE=Number;ProviderType=Int32'" />
</settings>
</oracle.dataaccess.client>

只需将 schema.storedproc 值替换为您的值。比如 ACCOUNTING.GET_EMPLOYEES。 并将 column_name_here 替换为您的列。如 EMP_ID。也去掉尖括号。

这里有全文供参考:http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/EntityFrameworkOBE/EntityFrameworkOBE.htm#t3

关于 XML 条目的文档:http://docs.oracle.com/cd/E11882_01/win.112/e18754/featImplRefCursor.htm#ODPNT319

【讨论】:

您不再需要手动创建包含元数据的配置文件,您也不想这样做。 “运行存储过程”向导会为您完成。 “文章”的链接非常过时。改用这个apex.oracle.com/pls/apex/…在本页其他地方查看我的答案。【参考方案2】:

现在 oracle 数据提供者允许这种操作没有太多麻烦。在这里回答太复杂了。添加了快速阅读。请点击以下链接了解详细信息。

ODP.NET 11g 第 2 版 (11.2.0.3.0) 及更高版本支持应用程序 在不使用 REF CURSOR 参数的情况下运行存储过程 在 .NET 代码中显式绑定这些参数。

对于只读结果集,例如使用 REF CURSOR OracleDataReader, REF CURSOR 模式信息被检索 自动。

对于某些情况,例如当可更新 REF CURSOR 或实体时 使用框架,开发者需要定义REF CURSOR schema 信息,以便应用程序可以绑定隐式 REF CURSOR。 实体框架应用程序使用隐式 REF CURSOR 绑定到 从 REF CURSOR 数据实例化复杂类型。应用程序必须 在 app.config 中指定 REF CURSOR 绑定和元数据信息, web.config 或 machine.config .NET 配置文件。

.NET 配置文件中提供的属性也被使用 当应用程序从 表示 REF CURSOR 的 OracleDataReader 对象。这意味着 对于使用单个表中的 SELECT 创建的 REF CURSOR, 应用程序可以通过使用更新该表 OracleDataAdapter 和 OracleCommandBuilder。

使用实体框架时,函数导入可以返回一个 隐式绑定的 REF CURSOR。 REF CURSOR 可以作为 复杂类型或实体类型的集合。返回复杂类型 集合,.NET配置文件需要定义REF CURSOR 绑定和元数据信息。要返回实体类型集合, 只有绑定信息需要在 .NET 中定义 配置文件。

查找完整信息here

【讨论】:

【参考方案3】:

要将导入功能与 EF 一起使用,您需要执行以下操作:

1) 参数列表中遇到的第一个 OUT SYS_REFCURSOR 将成为实体函数的输出。因此,您可能需要使用包含此 OUT SYS_REFCURSOR 的新 SP 包装您的 SP 或函数

2) 您需要在 app.config 或 web.config 中设置有关此光标的一些元数据。这是由服务器资源管理器中的“运行存储过程”对话框自动完成的。

您可以在此处查看分步演练: https://apex.oracle.com/pls/apex/f?p=44785:24:6479673193812:::24:P24_CONTENT_ID,P24_PROD_SECTION_GRP_ID,P24_PREV_PAGE:10068,,24

有关此主题的更多文档,请参阅 Oracle Developer Tools for Visual Studio 在线帮助的实体框架部分。

【讨论】:

【参考方案4】:

我也遇到过类似的问题。

经过长时间的研究,我发现 Oracle 对实体框架的支持尚未演变为使用复杂数据类型作为存储过程的返回类型。可以办到;但这就像在你的头上摸鼻子。因此,如果您为了方便而使用 EF,那么最好避免使用它并直接使用存储过程。

最后我决定使用 EF 创建、更新和删除(因为我必须实现审计跟踪)和返回结果集的存储过程。

【讨论】:

您好 - 那么您如何从 EF 调用 SP?像这样: var result = db.Database.SqlQuery("call OWI_ADMIN.S_LANDEN()"); ??【参考方案5】:

如果您想执行具有复杂返回类型和二进制字段的存储过程和函数,我认为使用 Entity 框架采用 oracle 方式并不是一个好方法。

【讨论】:

感谢您的回答。为了进一步帮助提问者,不仅要评论什么是不好的做法,还要评论什么是建设性的前进方式。在这种情况下,什么是好的或更好的方法?

以上是关于无法在实体框架中映射 SYS_REFCURSOR的主要内容,如果未能解决你的问题,请参考以下文章

如何在实体框架中映射 CONTAINSTABLE 函数(代码优先)?

更新映射到视图的实体框架实体

为啥实体框架没有映射我订单中的客户实体?

实体框架映射问题

使用实体框架映射数据库的方法?

实体框架中存储过程的返回值映射