dapper支持oracle游标

dapper支持oracle游标

Dapper是一个轻型的ORM类。它有啥优点、缺点相信很多朋友都知道了,园里也有很多朋友都有相关介绍,这里就不多废话。

如果玩过Oracle都知道,存储过程基本都是通过游标返回数据的,但是dapper原生操作游标会报异常,具体异常信息因为现在没有环境就不截图了。

复制代码
public FactoryPriceComparisonPublishItem GetTodayFactoryBasePricePushInfo(string weiXinId)
        {
            using (var cnn = Database.Connection("ERPDataBase"))
            {
                var p = new OracleDynamicParameters();
                p.Add("V_WEIXINID", weiXinId);
                p.Add("RetCursor", dbType: OracleDbType.RefCursor, direction: ParameterDirection.Output);
                return cnn.Query<FactoryPriceComparisonPublishItem>("PKG_M_STEELMILL.GetFactoryPCPublishItem", param: p, commandType: CommandType.StoredProcedure).SingleOrDefault();
            }
        }
复制代码

以上是实际项目的代码片段,通过游标获取查询数据。

那如何去解决这个游标问题呢?就是这个OracleDynamicParameters类,全部内容如下:

复制代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

using Dapper;
using Oracle.DataAccess.Client;

public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
    private static Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>();

    private Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
    private List<object> templates;

    private class ParamInfo
    {

        public string Name { get; set; }

        public object Value { get; set; }

        public ParameterDirection ParameterDirection { get; set; }

        public OracleDbType? DbType { get; set; }

        public int? Size { get; set; }

        public IDbDataParameter AttachedParam { get; set; }
    }

    /// <summary>
    /// construct a dynamic parameter bag
    /// </summary>
    public OracleDynamicParameters()
    {
    }

    /// <summary>
    /// construct a dynamic parameter bag
    /// </summary>
    /// <param name="template">can be an anonymous type or a DynamicParameters bag</param>
    public OracleDynamicParameters(object template)
    {
        AddDynamicParams(template);
    }

    /// <summary>
    /// Append a whole object full of params to the dynamic
    /// EG: AddDynamicParams(new {A = 1, B = 2}) // will add property A and B to the dynamic
    /// </summary>
    /// <param name="param"></param>
    public void AddDynamicParams(
#if CSHARP30
            object param
#else
dynamic param
#endif
)
    {
        var obj = param as object;
        if (obj != null)
        {
            var subDynamic = obj as OracleDynamicParameters;
            if (subDynamic == null)
            {
                var dictionary = obj as IEnumerable<KeyValuePair<string, object>>;
                if (dictionary == null)
                {
                    templates = templates ?? new List<object>();
                    templates.Add(obj);
                }
                else
                {
                    foreach (var kvp in dictionary)
                    {
#if CSHARP30
                            Add(kvp.Key, kvp.Value, null, null, null);
#else
                        Add(kvp.Key, kvp.Value);
#endif
                    }
                }
            }
            else
            {
                if (subDynamic.parameters != null)
                {
                    foreach (var kvp in subDynamic.parameters)
                    {
                        parameters.Add(kvp.Key, kvp.Value);
                    }
                }

                if (subDynamic.templates != null)
                {
                    templates = templates ?? new List<object>();
                    foreach (var t in subDynamic.templates)
                    {
                        templates.Add(t);
                    }
                }
            }
        }
    }

    /// <summary>
    /// Add a parameter to this dynamic parameter list
    /// </summary>
    /// <param name="name"></param>
    /// <param name="value"></param>
    /// <param name="dbType"></param>
    /// <param name="direction"></param>
    /// <param name="size"></param>
    public void Add(
#if CSHARP30
            string name, object value, DbType? dbType, ParameterDirection? direction, int? size
#else
string name, object value = null, OracleDbType? dbType = null, ParameterDirection? direction = null, int? size = null
#endif
)
    {
        parameters[Clean(name)] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size };
    }

    private static string Clean(string name)
    {
        if (!string.IsNullOrEmpty(name))
        {
            switch (name[0])
            {
                case '@':
                case ':':
                case '?':
                    return name.Substring(1);
            }
        }
        return name;
    }

    void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity)
    {
        AddParameters(command, identity);
    }

    /// <summary>
    /// Add all the parameters needed to the command just before it executes
    /// </summary>
    /// <param name="command">The raw command prior to execution</param>
    /// <param name="identity">Information about the query</param>
    protected void 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, false, false);
                        paramReaderCache[newIdent] = appender;
                    }
                }

                appender(command, template);
            }
        }

        foreach (var param in parameters.Values)
        {
            string name = Clean(param.Name);
            bool add = !((OracleCommand)command).Parameters.Contains(name);
            OracleParameter p;
            if (add)
            {
                p = ((OracleCommand)command).CreateParameter();
                p.ParameterName = name;
            }
            else
            {
                p = ((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.OracleDbType = param.DbType.Value;
            }
            if (add)
            {
                command.Parameters.Add(p);
            }
            param.AttachedParam = p;
        }
    }

    /// <summary>
    /// All the names of the param in the bag, use Get to yank them out
    /// </summary>
    public IEnumerable<string> ParameterNames
    {
        get
        {
            return parameters.Select(p => p.Key);
        }
    }

    /// <summary>
    /// Get the value of a parameter
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns>The value, note DBNull.Value is not returned, instead the value is returned as null</returns>
    public T Get<T>(string name)
    {
        var val = parameters[Clean(name)].AttachedParam.Value;
        if (val == DBNull.Value)
        {
            if (default(T) != null)
            {
                throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!");
            }
            return default(T);
        }
        return (T)val;
    }
}
复制代码

希望对大家有所帮忙,谢谢!

 
分类: orm
原文地址:https://www.cnblogs.com/Leo_wl/p/4984037.html