首页 > 代码库 > petapoco 对存储过程的扩展 干货

petapoco 对存储过程的扩展 干货

  好久没发表文章了。心血来潮,简单的介绍下这次工作中的问题。

项目中运用了Petapoco,可是petapoco对存储过程的支持不够好。或者说对于某些特殊场景,petapoco的sql支持度有限。

比如rowcount, 比如传入的字符创是{‘1‘,‘2‘}

因为我的项目是老系统改造,老系统很多奇怪的sql都有而且比较复杂,为了保证系统稳定,复杂sql还是沿用下来了。但这些历史遗留问题,就带来了附加问题。

 

原来打算用 petapoco+sqlhelper来处理,因为时间比较紧迫。不过2个connection下必须开启分布式事务才能解决一致性,觉得有点没有必要。

so 决定改造petapoco ,其实内部代码我已经改过很多了。petapoco很好扩展。就是侵入性有点强,必须要改源代码。

 

1.扩展存储过程

首先源代码需要修改的地方

       string _connectionString;        string _providerName;        DbProviderFactory _factory;        protected  IDbConnection _sharedConnection;       // IDbConnection _sharedConnection;  私有方法,不好扩展啊,必须改作用域        IDbTransaction _transaction;        int _sharedConnectionDepth;        int _transactionDepth;        bool _transactionCancelled;        string _lastSql;        object[] _lastArgs;        string _paramPrefix = "@";     

然后就可以在扩展类中实现需要的功能了。

对database进行扩展。

目前实现了2个功能

a.存储过程

b.打印sql.网上搜索的sql都是带参数的,和没打印一样。我直接输出结果了。

namespace Hg.Framework.Repository{    public class DataBaseE : Database    {        public DataBaseE(IDbConnection connection)            : base(connection)        {        }        public DataBaseE(string connectionString, string providerName)            : base(connectionString, providerName)        {        }        public DataBaseE(string connectionString, DbProviderFactory provider)            : base(connectionString, provider)        {        }        public DataBaseE(string connectionStringName)            : base(connectionStringName)        {        }       public SqlDataReader RunProcedure(string storedProcName, IDataParameter[] parameters)        {            try            {                OpenSharedConnection();                try                {                    SqlDataReader returnReader;                    SqlCommand command = BuildQueryCommand(_sharedConnection, storedProcName, parameters);                    command.CommandType = CommandType.StoredProcedure;                    returnReader = command.ExecuteReader(CommandBehavior.CloseConnection);                    return returnReader;                             }                finally                {                    CloseSharedConnection();                }            }            catch (Exception x)            {                OnException(x);                throw;            }        }       /// <summary>       /// 执行存储过程,返回影响的行数               /// </summary>       /// <param name="storedProcName">存储过程名</param>       /// <param name="parameters">存储过程参数</param>       /// <param name="rowsAffected">影响的行数</param>       /// <returns></returns>       public   int RunProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected)       {           try           {               OpenSharedConnection();               try               {                   int result;                    SqlCommand command = BuildIntCommand(_sharedConnection, storedProcName, parameters);                   rowsAffected = command.ExecuteNonQuery();                   result = (int)command.Parameters["ReturnValue"].Value;                   //Connection.Close();                   return result;               }               finally               {                   CloseSharedConnection();               }           }           catch (Exception x)           {               OnException(x);               throw;           }       }       /// <summary>       /// 创建 SqlCommand 对象实例(用来返回一个整数值)           /// </summary>       /// <param name="storedProcName">存储过程名</param>       /// <param name="parameters">存储过程参数</param>       /// <returns>SqlCommand 对象实例</returns>       private static SqlCommand BuildIntCommand(IDbConnection _connection, string storedProcName, IDataParameter[] parameters)       {           SqlConnection connection = _connection as SqlConnection;           SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters);           command.Parameters.Add(new SqlParameter("ReturnValue",               SqlDbType.Int, 4, ParameterDirection.ReturnValue,               false, 0, 0, string.Empty, DataRowVersion.Default, null));           return command;       }                /// <summary>                /// 构建 SqlCommand 对象(用来返回一个结果集,而不是一个整数值)                /// </summary>                /// <param name="connection">数据库连接</param>                /// <param name="storedProcName">存储过程名</param>                /// <param name="parameters">存储过程参数</param>                /// <returns>SqlCommand</returns>                private static SqlCommand BuildQueryCommand(IDbConnection _connection, string storedProcName, IDataParameter[] parameters)                {                    SqlConnection connection = _connection as SqlConnection;                    SqlCommand command = new SqlCommand(storedProcName, connection);                    command.CommandType = CommandType.StoredProcedure;                    foreach (SqlParameter parameter in parameters)                    {                        if (parameter != null)                        {                            // 检查未分配值的输出参数,将其分配以DBNull.Value.                            if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) &&                                (parameter.Value == null))                            {                                parameter.Value = DBNull.Value;                            }                            command.Parameters.Add(parameter);                        }                    }                    return command;                }        public override void OnExecutedCommand(IDbCommand cmd)        {            Debug.Print(FormatCommand2());            base.OnExecutedCommand(cmd);        }        private string FormatCommand2()        {            string sql = LastSQL;            object[] args = LastArgs;            if (sql == null)                return "";            string arg = "";            if (args != null && args.Length > 0)            {                for (int i = 0; i < args.Length; i++)                {                    switch (args[i].GetType().Name)                    {                        case "Int32":                        case "Decimal":                            arg = args[i].ToString();                            break;                        default:                            arg = "" + args[i].ToString() + "";                            break;                    }                    var fh = "@" + i;                    int startIndex = sql.IndexOf(fh);                    int charLength = startIndex + fh.Length;                 sql=   sql.Substring(0, charLength).Replace(fh, arg) + sql.Substring(charLength);                Log.Debug(sql,null);                    //sb.AppendFormat("\t -> {0}{1} [{2}] = \"{3}\"\n", "@", i, args[i].GetType().Name, args[i]);                }            }            return sql;        }    }}

 

好了。总体来说 petapoco还是很不错的。能满足大部分功能。如果能开放connection 和 transcation接口的话,会更灵活点。

OK,就到这里了。

petapoco 对存储过程的扩展 干货