DbHelper basic usage
对于使用微软的DataAccess Application Block的朋友,我这里有另一个选择,DbHelper。这是一个我做的Helper,用来满足自己的需求。这里介绍一下以便大家参考。
微软的DataAccess Application Block与DbHelper目的基本相同,它们没有谁好谁坏,只有适合与不适合,它们的区别在于:
- DbHelper的使用方式更简单。主要是因为把参数的部分简化了许多,现在根本不用生成参数了,但是对传入的参数对象也予以支持。
- DbHelper支持基本上所有的.NET下的Data Provider,而不只是SQL Server, Oracle与DB2,对其他非自带的Data Provider只需要实现一下获取其识别参数的方式就可以对其提供支持了,具体请见示例。
- 因为我不用存储过程,所以目前版本的DbHelper不支持存储过程。不过如果很多人需要的话我可以考虑添加这个功能。
以下为各种使用示例:
Executes a SQL commandusing Cavingdeep.Util.DataAccess;
// 创建一个SqlHelper的实例。
IDbHelper dbHelper = new SqlHelper(connection);
string insertCommandText = "INSERT INTO test VALUES (@text, @record_date)";
// 执行SQL命令。
dbHelper.ExecuteCommand(insertCommandText, "Text1", DateTime.Now);
// 创建一个SqlHelper的实例。
IDbHelper dbHelper = new SqlHelper(connection);
string insertCommandText = "INSERT INTO test VALUES (@text, @record_date)";
// 执行SQL命令。
dbHelper.ExecuteCommand(insertCommandText, "Text1", DateTime.Now);
就是这样简单,不用声明SQL参数,直接将参数值传入便可以了。不过当你需要明确指定参数类型等信息时也可以生成参数对象后传入,像以下示例。以下示例是一个混合模式的参数传入:
string insertCommandText = "INSERT INTO test VLAUES (@text, @record_date)";
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@record_date";
parameter.Value = DateTime.Now;
parameter.DbType = DbType.DateTime;
dbHelper.ExecuteCommand(insertCommandText, "Text1", parameter);
ExecuteReader
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@record_date";
parameter.Value = DateTime.Now;
parameter.DbType = DbType.DateTime;
dbHelper.ExecuteCommand(insertCommandText, "Text1", parameter);
string selectCommandText = "SELECT text, record_date FROM test WHERE text = @text";
using (IDataReader reader = dbHelper.ExecuteReader(selectCommandText, "Text1")) {
reader.Read();
this.textBox1.SelectedText = (string) reader["text"] + Environment.NewLine;
this.textBox1.SelectedText = reader["record_date"].ToString();
}
using (IDataReader reader = dbHelper.ExecuteReader(selectCommandText, "Text1")) {
reader.Read();
this.textBox1.SelectedText = (string) reader["text"] + Environment.NewLine;
this.textBox1.SelectedText = reader["record_date"].ToString();
}
Execute DataSet
string selectCommandText = "SELECT text, record_date FROM test WHERE text = @text";
DataSet ds = dbHelper.ExecuteDataSet("Test", selectCommandText, "Text1");
Transaction overloaded methods
DataSet ds = dbHelper.ExecuteDataSet("Test", selectCommandText, "Text1");
string insertCommandText = "INSERT INTO test VALUES (@text, @record_date)";
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
try {
dbHelper.ExecuteCommand(transaction, insertCommandText, "Text1", DateTime.Now);
transaction.Commit();
} catch {
transaction.Rollback();
} finally {
connection.Close();
}
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
try {
dbHelper.ExecuteCommand(transaction, insertCommandText, "Text1", DateTime.Now);
transaction.Commit();
} catch {
transaction.Rollback();
} finally {
connection.Close();
}
Extending support for other data providers
假设我们要对OLEDB进行支持,一般来说第一个步骤就是要实现IDbHelper接口,但是我们大可不必如此费事,DbHelper自带了一个默认支持多Data Provider的IDbHelper实现,这个实现就叫做"DbHelper",所以我们只要继承"DbHelper"就可以了,如下:using System.Data.OleDb;
public class OleDbHelper : DbHelper {
public OleDbHelper(OleDbConnection connection) :
base(connection, typeof(OleDbConnection), typeof(OleDbCommand),
typeof(OleDbParameter), typeof(OleDbDataAdapter),
new OleDbParameterRecognizer()) {}
}
public class OleDbHelper : DbHelper {
public OleDbHelper(OleDbConnection connection) :
base(connection, typeof(OleDbConnection), typeof(OleDbCommand),
typeof(OleDbParameter), typeof(OleDbDataAdapter),
new OleDbParameterRecognizer()) {}
}
将DbHelper需要的第三方data provider的各种类型传入DbHelper的构造方法中就可以了。不过值得注意的是还需要传入一个IParameterRecognizer,这个就是唯一需要我们自行实现的部分。IParameterRecognizer的作用是识别第三方data provider所支持的SQL参数的写法,比如SQL Server中是"@parameterName",OLEDB中要用"?"等等。这里我提供一个OleDb的IParameterRecognizer实现以供参考:
internal class OleDbParameterRecognizer : IParameterRecognizer {
private readonly Regex paramsRegex = new Regex(@"\?", RegexOptions.Compiled);
public string[] GetSqlParametersName(string commandText) {
if (commandText == null || commandText.Length == 0) {
throw new ArgumentNullException("commandText");
}
MatchCollection paramsNameMatches = this.paramsRegex.Matches(commandText);
ArrayList parameterNames = new ArrayList();
for (int i = 0; i < paramsNameMatches.Count; i++) {
parameterNames.Add(null);
}
return (string[]) parameterNames.ToArray(typeof(string));
}
}
private readonly Regex paramsRegex = new Regex(@"\?", RegexOptions.Compiled);
public string[] GetSqlParametersName(string commandText) {
if (commandText == null || commandText.Length == 0) {
throw new ArgumentNullException("commandText");
}
MatchCollection paramsNameMatches = this.paramsRegex.Matches(commandText);
ArrayList parameterNames = new ArrayList();
for (int i = 0; i < paramsNameMatches.Count; i++) {
parameterNames.Add(null);
}
return (string[]) parameterNames.ToArray(typeof(string));
}
}
基本上就是用正则表达式去找出符合规则的SQL参数,然后将参数名字添加到集合中,最后返回一个参数名的数组。注意OLEDB中是没有参数名的,所以每找到一个参数我就向集合中添加一个null值。
好了,一切都写好了后就可以完美的支持第三方data provider了。^_^