使用Dapper与返回游标的Oracle存储过程

如何将Dapper与返回游标的Oracle存储过程一起使用?

var p = new DynamicParameters(); p.Add("foo", "bar"); p.Add("baz_cursor", dbType: DbType.? , direction: ParameterDirection.Output); 

这里,DbType是System.Data.DbType,它没有Cursor成员。 我尝试过使用DbType.Object,但这对OracleClient和OracleDataAcess都不起作用。

相反,使用OracleType或OracleDbType的可能方法是什么?

你必须实现:

  public interface IDynamicParameters { void AddParameters(IDbCommand command, Identity identity); } 

然后在AddParameters回调中,您将IDbCommand转换为OracleCommand并添加DB特定的参数。

谢谢你的解决方案。 使用简单的DynamicParameter装饰器,我用更少的代码实现了同样的目的:

 public class OracleDynamicParameters : SqlMapper.IDynamicParameters { private readonly DynamicParameters dynamicParameters = new DynamicParameters(); private readonly List oracleParameters = new List(); public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null) { dynamicParameters.Add(name, value, dbType, direction, size); } public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction) { var oracleParameter = new OracleParameter(name, oracleDbType, 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()); } } } 

将此类添加到项目中

你的代码应该如下: –

  var p = new OracleDynamicParameters(); p.Add("param1", pAuditType); p.Add("param2", pCommnId); p.Add("outCursor", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output); using (var multi = cnn.QueryMultiple("procedure_name", param: p, commandType: CommandType.StoredProcedure)) { var data = multi.Read(); return data; } 

只是详细说明Sams的建议,这就是我想出的。 请注意,此代码很脆弱,现在只适用于Oracle。

修改后的Dapper 1.7

 void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity) { if (templates != null) { foreach (var template in templates) { var newIdent = identity.ForDynamicParameters(template.GetType()); Action appender; lock (paramReaderCache) { if (!paramReaderCache.TryGetValue(newIdent, out appender)) { appender = SqlMapper.CreateParamInfoGenerator(newIdent); paramReaderCache[newIdent] = appender; } } appender(command, template); } } foreach (var param in parameters.Values) { string name = Clean(param.Name); bool add = !((Oracle.DataAccess.Client.OracleCommand)command).Parameters.Contains(name); Oracle.DataAccess.Client.OracleParameter p; if(add) { p = ((Oracle.DataAccess.Client.OracleCommand)command).CreateParameter(); p.ParameterName = name; } else { p = ((Oracle.DataAccess.Client.OracleCommand)command).Parameters[name]; } var val = param.Value; p.Value = val ?? DBNull.Value; p.Direction = param.ParameterDirection; var s = val as string; if (s != null) { if (s.Length <= 4000) { p.Size = 4000; } } if (param.Size != null) { p.Size = param.Size.Value; } if (param.DbType != null) { p.DbType = param.DbType.Value; } if (add) { if (param.DbType != null && param.DbType == DbType.Object) { p.OracleDbType = Oracle.DataAccess.Client.OracleDbType.RefCursor; ((Oracle.DataAccess.Client.OracleCommand)command).Parameters.Add(p); } else { ((Oracle.DataAccess.Client.OracleCommand)command).Parameters.Add(p); } } param.AttachedParam = p; } } 

测试代码

 class Program { static void Main(string[] args) { OracleConnection conn = null; try { const string connString = "DATA SOURCE=XE;PERSIST SECURITY INFO=True;USER ID=HR;PASSWORD=Adv41722"; conn = new OracleConnection(connString); conn.Open(); var p = new DynamicParameters(); p.Add(":dep_id", 60); p.Add(":employees_c", dbType: DbType.Object, direction: ParameterDirection.Output); p.Add(":departments_c", dbType: DbType.Object, direction: ParameterDirection.Output); // This will return an IEnumerable // How do I return both result? var results = conn.Query("HR_DATA.GETCURSORS", p, commandType: CommandType.StoredProcedure); } catch (Exception exception) { Console.WriteLine(exception); throw; } finally { if (conn != null && conn.State == ConnectionState.Open) { conn.Close(); } } Console.WriteLine("Fininhed!"); Console.ReadLine(); } } class Employee { public int Employee_ID { get; set; } public string FIRST_NAME { get; set; } public string LAST_NAME { get; set; } public string EMAIL { get; set; } public string PHONE_NUMBER { get; set; } }