在 C# 中使用 Dapper 将数据发送到 RECORD 类型的 PL/SQL 脚本变量会更好吗
Posted
技术标签:
【中文标题】在 C# 中使用 Dapper 将数据发送到 RECORD 类型的 PL/SQL 脚本变量会更好吗【英文标题】:How is it better to send data using Dapper in c# to PL/SQL scripts variables of RECORD type 【发布时间】:2018-04-09 18:03:55 【问题描述】:我有一个 PL/SQL 过程,它使用 3 个 RECORD
类型的变量作为参数,我必须用我的数据(来自 c# 应用程序)填充这些变量来执行一个过程。
第一次我尝试通过 c# 使用此记录构建相同的结构并通过 Dapper 作为参数传递,但它不起作用,因为 dapper 仅适用于标量数据类型。
然后我尝试将我的数据作为数组传递并将它们映射到过程中,但是 RECORD 类型不能接受像a.NAME := ('aaaaaa','sdasd');
这样的数据集,它只能这样工作:
a.NAME(1) := 'aaaaaa';
a.NAME(2) := 'sdasd';
我现在唯一想到的就是在过程文本中生成这样的字符串,但我觉得应该有更好的方法。做错了什么?
附:毕竟我不能改变需要运行的脚本,所以我不能改变它接受的数据类型。
更新: 为了方便起见,假设我决定举个例子:
我们有 2 种自定义类型
TYPE A_REC IS RECORD (NAME dbms_sql.Varchar2_Table);
TYPE B_REC IS RECORD (NAME dbms_sql.Varchar2_Table
, ID dbms_sql.Number_Table);
和一个过程,可能会使用类似的东西
declare
a c_pck.a_rec;
b c_pck.b_rec;
begin
a.NAME(1) := 'aaaaa';
b.NAME(1) := 'sssss';
b.NAME(2) := 'ddddd';
b.ID(1) := 111;
b.ID(2) := 222;
c_pck.pr(a => a, b => b);
end;
如何通过 Dapper 运行此程序?
【问题讨论】:
【参考方案1】:我不能 100% 确定这是否适用于 PL\SQL,但是您可以将 SQL
表值参数传递到您从 Dapper 调用的存储过程中。 RECORD
类型听起来很像,所以它可以工作。
您需要使用DataTable
来构造您的RECORD
。您定义的列的顺序必须与它们在数据库中出现的顺序相同。
来自以下链接:
var dt = new DataTable();
dt.Columns.Add("AUDIT_PK", typeof (long));
dt.Columns.Add("MESSAGE", typeof (string));
dt.Columns.Add("SUCCESS", typeof (bool));
dt.Rows.Add(1, "EHLO", null);
using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Scratch;Integrated Security=true"))
conn.Open();
conn.Execute("TestOne", new TVP = dt.AsTableValuedParameter("dbo.AUDITRECORD"), commandType: CommandType.StoredProcedure);
https://www.codeproject.com/Articles/835519/Passing-Table-Valued-Parameters-with-Dapper
【讨论】:
以这种方式在Oracle.ManagedDataAccess.Client.OracleParameter.set_Value(Object value)
中获取System.ArgumentException: value out of range
在Dapper.TableValuedParameter.Set(IDbDataParameter parameter, DataTable table, String typeName)
等中【参考方案2】:
你需要在这里处理两个不同的事情。
-
告知 Oracle 驱动程序您的自定义数据类型
在这里,您将需要相当多的样板文件。
您必须使用IOracleCustomType
接口为您的UDT 编写映射代码。 Here's官方文档。 This guide 似乎是一个很好的资源。
-
向 Dapper 介绍您的自定义数据类型
Dapper 有一个硬编码的 .NET 类型列表,映射到 DbTypes。
您可以添加到此列表,但只能添加到通用 DbTypes。
要使用特定于数据库的功能,您的参数必须实现
SqlMapper.ICustomQueryParameter
(这就是表值
SQL server 工作的东西)。在您的AddParameter
实现中,您可以手动构造一个OracleParameter
并正确设置UDT 类型名。
返回值应该由 Dapper 处理得很好,因为这只是映射像
【讨论】:
听起来很有趣,但我使用的是 Oracle,而不是 PG 会寻找这样的东西 那是我将 PL/SQL 完全误读为 PLPGSQL。对此感到抱歉:-) 无论如何,控制如何创建参数的简洁界面将是相同的。那么我认为你必须查看OracleCustomTypeMapping
属性来指导Oracle 关于你的数据。
想在我可以访问的 oracle 开发基础上做一些快速测试,但不幸的是,“ODP.NET,托管驱动程序不支持 UDT 和 .NET 自定义类型”。我没有用不受管理的东西污染我的视觉工作室,对不起:)以上是关于在 C# 中使用 Dapper 将数据发送到 RECORD 类型的 PL/SQL 脚本变量会更好吗的主要内容,如果未能解决你的问题,请参考以下文章