drapper oracle,在Oracle中使用Dapper QueryMultiple

博客内容讲述了在使用Dapper的QueryMultiple()方法与Oracle数据库配合时遇到的ORA-00933错误。作者详细解析了问题的原因,即Oracle不支持多查询语法,并提供了解决方案,即使用游标和动态参数来处理。作者还分享了一个自定义的OracleDynamicParameters类,用于处理Oracle数据库的参数设置。最后,展示了完整代码示例,演示如何正确查询和获取多个结果集。

OP可能早就解决了这个问题,但是在撰写本文时,这个问题只有一个答案,并没有真正解决使用Dapper的QueryMultiple()方法与Oracle的问题.由于@ Kamolas81正确地陈述,通过使用官方示例中的语法,确实会得到ORA-00933:sql命令没有正确结束的错误消息.我花了一段时间来搜索关于如何使用Oracle的QueryMultiple()的一些文档,但我很惊讶,没有一个地方有一个答案.我会认为这是一个相当普遍的任务.我虽然在这里发布了一个答案来拯救我:)有些人在将来有一段时间,以防万一碰巧有同样的问题.

Dapper似乎只是直接传递sql命令到ADO.NET,无论数据库提供者正在执行命令.在示例中的语法中,每个命令以换行符分隔,sql Server将将其解释为针对数据库运行的多个查询,它将运行每个查询并将结果返回到单独的输出.我不是一个ADO.NET的专家,所以我可能会搞砸这个术语,但是最终的效果是Dapper得到了多个查询输出,然后才起作用.

但是,Oracle不能识别多个查询;它认为sql命令格式错误,并返回ORA-00933消息.解决方案是使用游标并在DynamicParameters集合中返回输出.例如,sql Server版本如下所示:

var sql =

@"

select * from Customers where CustomerId = @id

select * from Orders where CustomerId = @id

select * from Returns where CustomerId = @id";

Oracle版本的查询将需要如下所示:

var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +

"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +

"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +

"END;";

对于针对sql Server的查询,Dapper可以从那里处理它.但是,由于我们将结果集返回到游标参数中,因此我们需要使用IDynamicParameters集合来指定命令的参数.要添加额外的皱纹,Dapper中的常规DynamicParameters.Add()方法对可选的dbType参数使用System.Data.DbType,但查询的游标参数需要为Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor类型.为了解决这个问题,我使用了@Daniel Smith在this answer中提出的解决方案,并创建了一个IDynamicParameters接口的自定义实现:

using Dapper;

using Oracle.ManagedDataAccess.Client;

using System.Data;

public class OracleDynamicParameters : sqlMapper.IDynamicParameters

{

private readonly DynamicParameters dynamicParameters = new DynamicParameters();

private readonly List oracleParameters = new List();

public void Add(string name,OracleDbType oracleDbType,ParameterDirection direction,object value = null,int? size = null)

{

OracleParameter oracleParameter;

if (size.HasValue)

{

oracleParameter = new OracleParameter(name,oracleDbType,size.Value,value,direction);

}

else

{

oracleParameter = new OracleParameter(name,direction);

}

oracleParameters.Add(oracleParameter);

}

public void Add(string name,ParameterDirection direction)

{

var oracleParameter = new OracleParameter(name,direction);

oracleParameters.Add(oracleParameter);

}

public void AddParameters(IDbCommand command,sqlMapper.Identity identity)

{

((sqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command,identity);

var oracleCommand = command as OracleCommand;

if (oracleCommand != null)

{

oracleCommand.Parameters.AddRange(oracleParameters.ToArray());

}

}

}

所以所有的代码都是这样的:

using Dapper;

using Oracle.ManagedDataAccess.Client;

using System.Data;

int selectedId = 1;

var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +

"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +

"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +

"END;";

OracleDynamicParameters dynParams = new OracleDynamicParameters();

dynParams.Add(":rslt1",OracleDbType.RefCursor,ParameterDirection.Output);

dynParams.Add(":rslt2",ParameterDirection.Output);

dynParams.Add(":rslt3",ParameterDirection.Output);

dynParams.Add(":id",OracleDbType.Int32,ParameterDirection.Input,selectedId);

using (IDbConnection dbConn = new OracleConnection(""))

{

dbConn.Open();

var multi = dbConn.QueryMultiple(sql,param: dynParams);

var customer = multi.Read().Single();

var orders = multi.Read().ToList();

var returns = multi.Read().ToList();

...

dbConn.Close();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值