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

项目中运用了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, , ParameterDirection.ReturnValue,
false, , , 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 > )
{
for (int i = ; 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(, 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 对存储过程的扩展 干货的更多相关文章

  1. 针对thinkphp 5框架存储过程bug而重写的存储过程的扩展类

    近期用tp5框架调取存储过程发现有bug,借鉴了一些官方的函数.以及找了个mysqli的类把存储过程重新写了个扩展类,下面两个类直接放置项目extend目录的stored(这个文件夹名称请按个人习惯命 ...

  2. PetaPoco 访问SQL SERVER 存储过程

    博客园有篇文章<小巧方便的ORM类库——PetaPoco>  介绍了PetaPoco调用存储过程: //调用存储过程 db.Execute("exec procSomeHandl ...

  3. SQL Server里一些未公开的扩展存储过程

    SQL Server里一些未公开的扩展存储过程 [转帖] 博客天地 www.inbaidu.com SQL Server里一些未公开的扩展存储过程 扩展存储过程(xp)是直接运行在SQL Server ...

  4. Sql Server系列:存储过程

    1 存储过程简介 存储过程是使用T-SQL代码编写的代码段.在存储过程中,可以声明变量.执行条件判断语句等其他编程功能.在MS SQL Server 2012中存储过程主要分三类:系统存储过程.自定义 ...

  5. 详解SQLServer 存储过程

    Sql Server的存储过程是一个被命名的存储在服务器上的Transacation-Sql语句集合,是封装重复性工作的一种方法,它支持用户声明的变量.条件执行和其他强大的编程功能. 存储过程相对于其 ...

  6. DBA工具——DMV——通过sys.dm_exec_procedure_stats查看存储过程执行信息

    原文:DBA工具--DMV--通过sys.dm_exec_procedure_stats查看存储过程执行信息 对于DBA来说,经常要手机存储过程的某些信息: 执行了多少次 执行的执行计划如何 执行的平 ...

  7. SQL Server——存储过程

    我想从下面几个方面大概的讲述下存储过程,可能有些知识点是你没有注意的,也可能有些知识点我不知道,欢迎大家指点指点.如有不足,欢迎指教! 存储过程概念 存储过程优点 存储过程的接口 存储过程的解析.编译 ...

  8. 存储过程学习笔记(SQL数据库

    一.   存储过程简介 Sql Server的存储过程是一个被命名的存储在服务器上的Transacation-Sql语句集合,是封装重复性工作的一种方法,它支持用户声明的变量.条件执行和其他强大的编程 ...

  9. BCP SQL导出EXCEL常见问题及解决方法;数据导出存储过程

    一.‘xp_cmdshell’的启用 SQL Server阻止了对组件‘xp_cmdshell’的过程‘sys.xp_cmdshell’的访问.因为此组件已作为此服务嚣安全配置的一部分而被关 闭.系统 ...

随机推荐

  1. Skype 服务器客户端策略参数优化

    1.skype通讯录原理 对于skype客户端的通讯录同步,首先说说原理,通讯簿信息是从AD同步的skype前端服务器(每天1:30),在从前端服务器同步的客户端(大概1小时内同步一次). skype ...

  2. MySQL主从复制异步原理以及搭建

    MySQL主从复制的原理: 1.首先,MySQL主库在事务提交时会把数据变更作为时间events记录在二进制日志文件binlog中:MySQL主库上的sync_binlog参数控制Binlog日志以什 ...

  3. iOS 固定定位不兼容、input获取焦点后位置不对。

    第一次写博客~  大家悠着看,有则改之,无则加冕,对不对的给个回复,让我知道你的存在. 在做活动页的时候,经常会碰到一些需要弹出显示的输入框(情节前提:本人安卓机~),前天自己写的时候自己调试没问题后 ...

  4. DOM相关方法,属性整理

    DOM相关方法,属性整理1.获取元素的方法 1根据id获取对象 document.getElementById(''); 2根据标签名获取对象 document.getElementsByTagNam ...

  5. [ML学习笔记] XGBoost算法

    [ML学习笔记] XGBoost算法 回归树 决策树可用于分类和回归,分类的结果是离散值(类别),回归的结果是连续值(数值),但本质都是特征(feature)到结果/标签(label)之间的映射. 这 ...

  6. bootstrap模态框input不能获取焦点并编辑【转】

    Bootstrap模态框时input标签[日期控件也有这样的问题]不能编辑的问题,下面是我的解决方法: 1.将下图中框出来的属性删掉即可: 2.兼容火狐浏览器,笔者在火狐中还是不能编辑,去掉下图属性即 ...

  7. 谁对EXTJS熟悉,有关关闭panel的问题?

    谁对EXTJS熟悉,有关关闭panel的问题?比如:我在A.js 中写了一个  var  win  =   new  Ext.Window( { b.js });   win.show(); 打开了一 ...

  8. canvas实例_时钟

    效果图:是一个会动的时钟 一.时钟的组成 1.表盘(蓝色)  2.刻度(黑色)  3.时针(黑色)  4.分针(黑色)  5.秒针(红色)需美化     二.主要应用的技术 Canvas画线 Canv ...

  9. HTML5中的Canvas详解

    什么是Canvas HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成.<canvas> 标签只是图形容器,您必须使用脚本来绘制图 ...

  10. Docker介绍-hc课堂笔记

    1,传统模式-多个服务器:申请.安装jdk等.部署环境. 容器-整包,把有东西打包到一起,把这个包放在服务器上. linux中装了docker,起100个服务,改个数字就可以,5分钟左右. 2,虚拟化 ...