我有一个PL / SQL程序,使用3个RECORD
类型的变量作为参数,我必须填写我的数据(来自c#应用程序)来执行一个程序。
我试图通过c#与这些记录构建相同的结构,并通过Dapper作为参数传递,但由于dapper仅适用于标量数据类型,因此无法正常工作。
然后我试图将我的数据作为数组传递并将它们映射到过程中,但是RECORD类型不能接受像a.NAME := ('aaaaaa','sdasd');
这样的数据集,它只能以这种方式工作:
a.NAME(1) := 'aaaaaa';
a.NAME(2) := 'sdasd';
我现在唯一想到的就是在程序文本中生成这样的字符串,但我觉得应该有更好的方法。怎么了?
P.S。毕竟我无法更改需要运行的脚本,所以我无法更改它接受的数据类型。
更新: 为了方便起见,让我们说,我已经决定做一个例子:
我们有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运行此程序?
答案 0 :(得分:0)
我不能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
答案 1 :(得分:0)
你需要在这里处理两件事。
在这里,你需要大量的样板。
您必须使用IOracleCustomType
接口为UDT编写映射代码。 Here's官方文件。 This guide似乎是一个很好的资源。
Dapper有一个映射到DbTypes的.NET类型的硬编码列表。
您可以添加到此列表,但仅添加到通用DbTypes。
要使用特定于数据库的功能,您的参数必须实现
SqlMapper.ICustomQueryParameter
(这是表值的方式
SQL服务器工作的东西)。在AddParameter
实现中,您可以手动构造OracleParameter
并正确设置UDT类型名称。
Dapper应该正确处理返回值,因为这只是映射结果集,如