共享一个数据库帮助器

Ivony 2006-02-28 01:41:08
关于事务方面的代码还在修改完善中,也许不会那样做,但是有很多功能已经很成熟了,自己觉得比那个什么糟糕的SqlHelper还是好多了。

给分的原则,mark最多2分,顶、up、接分、JF等无分。

批评和建设性意见酌情给分。


====DbUtility.cs====


namespace Ivony.Data
{
public abstract class DbUtility
{


#region 抽象方法

/// <summary>
/// 由派生类实现,创建IDbCommand对象
/// </summary>
/// <param name="newConnection">指定是否同时创建新的数据库连接对象</param>
protected abstract IDbCommand CreateCommand( bool newConnection );

/// <summary>
/// 由派生类实现,创建IDataAdapter对象
/// </summary>
/// <param name="selectCommand">查询命令</param>
protected abstract IDataAdapter CreateDataAdapter( IDbCommand selectCommand );

/// <summary>
/// 由派生类实现,创建IDataParameter对象
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
protected abstract IDataParameter CreateParameter( string name, object value );

#endregion


protected bool _alwaysCreateConnection = true;

/// <summary>
/// 指示是否总是创建新的连接
/// </summary>
public virtual bool AlwaysCreateConnection
{
get { return _alwaysCreateConnection; }
set { _alwaysCreateConnection = value; }
}

protected bool _hideConnection;
/// <summary>
/// 指示是否已经将数据库连接隐藏,即Connection等属性不可用。
/// </summary>
public bool HideConnection
{
get { return _hideConnection; }
}


private CommandParserOptions _parserOptions;
/// <summary>
/// 设定命令解释器的参数
/// </summary>
public CommandParserOptions ParserOptions
{
get { return _parserOptions; }
set { _parserOptions = value; }
}


#region IDbUtility Members

/// <summary>
/// 填充DataSet,并将填充的最后一个表返回
/// </summary>
/// <param name="commandText">查询字符串模板</param>
/// <param name="parameters">查询字符串参数</param>
/// <returns></returns>
public virtual DataTable ExecuteData( string commandText, params object[] parameters )
{
return ExecuteData( null, null, commandText, parameters );
}

/// <summary>
/// 填充DataSet,并将填充的最后一个表返回
/// </summary>
/// <param name="dataSet">需要被填充的数据集</param>
/// <param name="tableName">将最后一个表设置为什么名字</param>
/// <param name="commandText">查询字符串模板</param>
/// <param name="parameters">查询字符串参数</param>
/// <returns></returns>
public virtual DataTable ExecuteData( DataSet dataSet, string tableName, string commandText, params object[] parameters )
{
return ExecuteData( CreateDataAdapter( CreateCommand( commandText, parameters ) ), dataSet, tableName );
}

/// <summary>
/// 执行无结果的查询
/// </summary>
/// <param name="commandText">查询字符串模板</param>
/// <param name="parameters">查询字符串参数</param>
/// <returns></returns>
public virtual int ExecuteNonQuery( string commandText, params object[] parameters )
{
return ExecuteNonQuery( CreateCommand( commandText, parameters ) );
}

/// <summary>
/// 执行查询,并返回首行首列
/// </summary>
/// <param name="commandText">查询字符串模板</param>
/// <param name="parameters">查询字符串参数</param>
/// <returns></returns>
public virtual object ExecuteScalar( string commandText, params object[] parameters )
{
return ExecuteScalar( CreateCommand( commandText, parameters ) );
}

/// <summary>
/// 执行查询,并返回首行
/// </summary>
/// <param name="commandText">查询字符串模板</param>
/// <param name="parameters">查询字符串参数</param>
/// <returns></returns>
public virtual DataRow ExecuteSingleRow( string commandText, params object[] parameters )
{
return ExecuteSingleRow( CreateCommand( commandText, parameters ) );
}

#endregion

...全文
647 46 打赏 收藏 转发到动态 举报
写回复
用AI写文章
46 条回复
切换为时间正序
请发表友善的回复…
发表回复
stepman 2006-06-15
  • 打赏
  • 举报
回复
好东西,谢谢楼主
cherish58 2006-06-14
  • 打赏
  • 举报
回复
顶先
fredlin 2006-04-27
  • 打赏
  • 举报
回复
这个....net2003的怎么用?
Radar2006 2006-04-27
  • 打赏
  • 举报
回复
mark&学习啦
Ivony 2006-04-26
  • 打赏
  • 举报
回复
还有一点说明一下,有一些高级功能仅在SqlDbUtility这样的具体类中提供,而不是抽象到DbUtility,是因为DbUtility提供的功能已经能够满足大多数情况所需,有些功能是与数据库紧密相关的,抽象反而带来大量的兼容代码,属于过度设计!
即使用到了那些功能,现在IDE的重构和替换功能已经足够强大,代码修改的程度和难度也不会很大,相较于数据库的迁移,这个东西已经可以忽略不计,因为大部分的功能已经抽象。

你可以这样写:
DbUtility dbUtlity = new SqlDbUtility( sqlConnectionString );

然后,要用到高级功能:

((SqlDbUtility) dbUtility).XXXXX

还有一些是现在SqlDbUtility里面实现,现在还没有抽象到DbUtility的……
Ivony 2006-04-26
  • 打赏
  • 举报
回复
我不是高手,我只是想问一下,楼主你上边的代码中二次开发强吗?给我的感觉悟,并没有很好的遵守面向对像的开发中“开闭”原则,扩展性不好,好像对数据库类别依赖有点强!

====================================================

DbUtility是数据库无关的,我只写了SqlDbUtility而已,其他的因为现在根本用不着,我也懒得写。

扩展性还是很强的,DbUtility这个公共基类只处理了一些非常基本的东西,与数据库相关的东西,甚至是连接的开闭都是可以由派生类自己去定义的。
例如CreateCommand虽然有个newConnection参数,但是派生类也可以完全不理会这个参数。

至于参数的创建,不同的数据库要求不同的参数格式,所以DbUtility并没有自己亲自去创建参数,参数的名字是由CommandParser创建的,参数的实体是由DbUtility的派生类根据value的类型创建出来的。只要对不同的数据库使用不同的CommandParser并重写CreateParameter方法就可以搞定所有的数据库。

StoredProcedure也是采用了同样的方式。

再解释几点。
为什么不像其他的数据库提供程序一样从Session入手,这是因为我现在主要搞ASP.NET开发,ASP.NET的特殊性使得什么Session的概念根本不能实现(每一个页面都是一个线程,并且你还不知道他会不会中途放弃,要保持数据库连接跨页面是绝对不行的。而在一个页面的处理程序中Session的概念显得多余。)

为什么不做ORM、数据库实体等东西?因为我觉得那是过度设计。
这个东西的唯一目的就是省代码,而不是给你订框架,就是删掉那些亢余的代码而已,让SQL语句的调用更加轻松并且不会有注入式漏洞。
那个DAAB,代码没省多少,里面的垃圾一大堆……,看都看死人,我很难去相信一个代码都看不清的东西。So,才有了这个东西……
-渔民- 2006-04-26
  • 打赏
  • 举报
回复
这样的话,那我就不要分,我up!
学习啦
fredlin 2006-04-26
  • 打赏
  • 举报
回复
xuexi
泡沫游走 2006-04-25
  • 打赏
  • 举报
回复
mark
先得2分,以后研究!
yybb520 2006-04-25
  • 打赏
  • 举报
回复
我不是高手,我只是想问一下,楼主你上边的代码中二次开发强吗?给我的感觉悟,并没有很好的遵守面向对像的开发中“开闭”原则,扩展性不好,好像对数据库类别依赖有点强!
Ivony 2006-04-25
  • 打赏
  • 举报
回复
try{}finally{}为什么要这么写?

=================================================


因为如果数据库连接是自己开的,自己就有责任把他关掉,总不能告诉调用方,每调用一次就还要关一下连接吧。为什么不使用using?因为那个Connection对象可能还要用到的,不能Dispose。
dojoin 2006-04-25
  • 打赏
  • 举报
回复
try{}finally{}为什么要这么写?
  • 打赏
  • 举报
回复
收藏
boy_north 2006-04-25
  • 打赏
  • 举报
回复
这个是封装的好
值的学习!
但不知道灵活性怎么样
AllenIverson 2006-04-10
  • 打赏
  • 举报
回复
mark
Ivony 2006-04-10
  • 打赏
  • 举报
回复
范例:
SqlDbUtility dbUtility = new SqlDbUtility( connectionString );
DataRow data = dbUtility.ExecuteSingleRow( "SELECT * FROM MyTable WHERE ID = {0}", 5 );


存储过程:
SqlDbUtility dbUtility = new SqlDbUtility( connectionString );
SqlStoredProcedure MyStoredProcedure = dbUtility.CreateStoredProcedure( "MyStoredProcedure" );
MyStoredProcedure["Name"] = name;
MyStoredProcedure["Address"] = address;
int ReturnValue = MyStoredProcedure.Execute();
Ivony 2006-04-10
  • 打赏
  • 举报
回复
汗挖,竟然漏了一个文件。


===FormatUtility.cs 节选===

using System;
using System.Text.RegularExpressions;


#pragma warning disable 1591
#warning 1591 disabled

namespace Ivony
{
public sealed class FormatUtility
{
public static readonly Regex FormatRegex = new Regex( @"\{((?<index>[0-9]+)\#)?(?<name>[a-zA-Z_]*)(,(?<alignment>[0-9]+[a-zA-Z]*))?(\:(?<format>[^{}]*))?\}", RegexOptions.Compiled );//匹配类似于这样的字符串:{0#date,6:yyyy-mm-dd},用于数据绑定。
public static readonly Regex FormatRegexNum = new Regex( @"\{(?<index>[0-9]*)(,(?<alignment>[0-9]+[a-zA-Z]*))?(\:(?<format>[^{}]*))?\}", RegexOptions.Compiled );//匹配类似于这样的字符串:{1,5:@Name},用于分析数字序号格式化字符串。

private FormatUtility(){}

/// <summary>
/// 截获定长的字符串
/// </summary>
/// <param name="source">源字符串</param>
/// <param name="length">需要截获的长度</param>
/// <returns>截获后的字符串</returns>
static public string FixLenth ( string source, int length)
{
return FixLenth ( source, length, "...");
}
/// <summary>
/// 截获定长的字符串
/// </summary>
/// <param name="source">源字符串</param>
/// <param name="length">需要截获的长度</param>
/// <param name="postfix">如果字符串被截短,需要添加什么样的后缀</param>
/// <returns>截获后的字符串</returns>
static public string FixLenth ( string source, int length, string postfix)
{
if ( source == null )
throw new ArgumentNullException( "source" );
if ( postfix == null )
postfix = "...";

if ( length < postfix.Length )
throw new ArgumentOutOfRangeException( "length" );


int postfixLength = System.Text.Encoding.GetEncoding("GB2312").GetByteCount( postfix);
int srcLength = System.Text.Encoding.GetEncoding("GB2312").GetByteCount( source);

if ( srcLength > length)
{
for ( int i = source.Length; i>0; i--)
{
srcLength = System.Text.Encoding.GetEncoding("GB2312").GetByteCount( source.Substring(0,i) );

if ( srcLength <= length - postfixLength)
return source.Substring(0,i) + postfix;
}
return "";
}
else
return source;
}
}
}
chinadforce 2006-04-10
  • 打赏
  • 举报
回复
CommandParser.cs中
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;

/// <summary>
/// 分析处理命令字符串
/// </summary>
/// <param name="commandText">命令字符串</param>
/// <param name="parameters">需要被替换进去的参数列表</param>
public void ParseCommandText(ref string commandText, ref object[] parameters)
{
_parameters = parameters;

commandText = commandText.Replace("{...}", ParseParameterListSymbol(parameters.Length));


commandText = FormatUtility.FormatRegexNum.Replace(commandText, ParseParameter);
parameters = _dataParameters.ToArray();
}中 FormatUtility这个要怎么引用???
pshy 2006-04-10
  • 打赏
  • 举报
回复
收藏起来慢慢看,学习。。。
shamao 2006-04-10
  • 打赏
  • 举报
回复
推荐一个开源项目。
www.websharp.org
里面有关于NET操作数据库的比较灵活的办法。
加载更多回复(25)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧