如何将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的可能方法是什么?
答案 0 :(得分:8)
感谢此处的解决方案。使用简单的动态参数装饰器,我用更少的代码实现了同样的目的:
public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
private readonly DynamicParameters dynamicParameters = new DynamicParameters();
private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
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());
}
}
}
答案 1 :(得分:6)
您必须实施:
public interface IDynamicParameters
{
void AddParameters(IDbCommand command, Identity identity);
}
然后在AddParameters
回调中,您将IDbCommand
转换为OracleCommand
并添加数据库特定的参数。
答案 2 :(得分:4)
将this课程添加到您的项目中
您的代码应如下所示: -
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;
}
答案 3 :(得分:3)
只是详细说明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<IDbCommand, object> 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<Employee> // How do I return both result?
var results = conn.Query<Employee>("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; }
}