基於微軟企業庫4.1的SQLHelper
上面是下载 链接:
其實以前封裝過SQLHelper类,所以這次輕車駕熟,先來看看SQLHelper這個Static類提供的public成員。
返回結果為DataSet的方法:
ExecuteDataSetBySql:
執行Sql語句,將返回一個 DataSet
ExecuteDataSetBySqlTran:
以事務方式執行多條Sql語句,將每條sql執行的結果集合并到一個 DataSet且將其返回。
ExecuteDataSetByStoredProced:
執行存儲過程,返回一個 DataSet
返回結果是受影響行數的方法:
ExecuteNonQueryBySql:
執行Sql語句,返回受影响的行数。
ExecuteNonQueryBySqlTran:
以事務方式執行多條Sql語句,返回受影响的行数總和。
ExecuteNonQueryByStoredProced:
執行存儲過程,返回受影响的行数。
返回結果是第一行第一列的方法:
ExecuteScalarBySql:
執行Sql語句,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
ExecuteScalarBySqlTran:
以事務方式執行多條Sql語句,返回查詢結果集的一個列表
ExecuteScalarByStoredProced:
執行存儲過程,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
ResetDatabase:重新設置數據庫。
UpdateDataSet:为指定的 DataSet 數據集同步到數據庫。
注意:類庫中看到的重載,其實就是方法接受的參數不一樣。但是重載方法的功能是一致的。
先實現執行單SQL語句的方法。
public static Database database = DatabaseFactory.CreateDatabase();
/// <summary>
/// 執行一條Sql語句,將返回一個 DataSet
/// </summary>
/// <param name="sqlString">sql語句</param>
/// <returns>返回一個 DataSet</returns>
public static DataSet ExecuteDataSetBySql(string sqlString)
{
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
return database.ExecuteDataSet(dbCommand);
}
/// <summary>
/// 執行一條Sql語句,將返回受影响的行数。
/// </summary>
/// <param name="sqlString">sql語句</param>
///<returns>返回受影响的行数。</returns>
public static int ExecuteNonQueryBySql(string sqlString)
{
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
return database.ExecuteNonQuery(dbCommand);
}
/// <summary>
/// 執行一條Sql語句,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
/// </summary>
/// <param name="sqlString">sql語句</param>
///<returns>返回结果集中第一行的第一列。</returns>
public static object ExecuteScalarBySql(string sqlString)
{
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
return database.ExecuteScalar(dbCommand);
}
實現的代碼非常簡單,但是當中有重複代碼,就是每個方法中都有
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
這么一句重複代碼,為了滿足沒有重複代碼的要求。
開始第一次重構。
private static DbCommand GetSqlStringCommand(string sqlString)
{
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
return dbCommand;
}
/// <summary>
/// 執行一條Sql語句,將返回一個 DataSet
/// </summary>
/// <param name="sqlString">sql語句</param>
/// <returns>返回一個 DataSet</returns>
public static DataSet ExecuteDataSetBySql(string sqlString)
{
return database.ExecuteDataSet(GetSqlStringCommand(sqlString));
}
/// <summary>
/// 執行一條Sql語句,將返回受影响的行数。
/// </summary>
/// <param name="sqlString">sql語句</param>
///<returns>返回受影响的行数。</returns>
public static int ExecuteNonQueryBySql(string sqlString)
{
return database.ExecuteNonQuery(GetSqlStringCommand(sqlString));
}
/// <summary>
/// 執行一條Sql語句,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
/// </summary>
/// <param name="sqlString">sql語句</param>
///<returns>返回结果集中第一行的第一列。</returns>
public static object ExecuteScalarBySql(string sqlString)
{
return database.ExecuteScalar(GetSqlStringCommand(sqlString));
}
這次重構的目的就是提取相同的代碼,提高代碼重用性。
仔細的觀察上面三個方法。參數一致,方法內只執行一個方法, 返回值不同。
這讓我想到了泛型方法。可是泛型方法一時行不通,因為三個方法體內執行的方法不一致,不能直接提取。
如果能把方法當成參數傳遞就好,就這樣泛型方法就行得通了。
沒錯,委托能幫我做到把方法當成參數傳遞。
開始第二次重構。
public delegate T ExecuteBySqlHandle<T>(DbCommand dbCommand);
private static T ExecuteBySql<T>( ExecuteBySqlHandle<T> executeBySql, string sqlString)
{
DbCommand dbCommand = database.GetSqlStringCommand(sqlString);
return executeBySql.Invoke(dbCommand);
}
/// <summary>
/// 執行Sql語句,將返回一個 DataSet
/// </summary>
/// <param name="sqlString">Sql語句</param>
/// <returns>返回一個 DataSet</returns>
public static DataSet ExecuteDataSetBySql(string sqlString)
{
return ExecuteBySql<DataSet>(
new ExecuteBySqlHandle<DataSet>(database.ExecuteDataSet),
sqlString);
}
/// <summary>
/// 執行Sql語句,返回受影响的行数。
/// </summary>
/// <param name="sqlString">Sql語句</param>
///<returns>返回受影响的行数。</returns>
public static int ExecuteNonQueryBySql(string sqlString)
{
return ExecuteBySql< int >(
new ExecuteBySqlHandle< int >(database. ExecuteNonQuery),
sqlString);
}
/// <summary>
/// 執行Sql語句,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
/// </summary>
/// <param name="sqlString">Sql語句</param>
///<returns>返回结果集中第一行的第一列。</returns>
public static object ExecuteScalarBySql(string sqlString)
{
return ExecuteBySql< object >(
new ExecuteBySqlHandle< object >(database.ExecuteScalarBySql),
sqlString);
}
第二次重構后,代碼已經足夠復用和抽象。只是美中不足的就是那個委托參數老長。其實3.5框架中,已經支持匿名推斷類型,所以傳遞委托的時候可以不new,直接傳相應的方法就可以了。泛型方法和委托不變,優化下三個執行SQL的方法。
/// <summary>
/// 執行Sql語句,將返回一個 DataSet
/// </summary>
/// <param name="sqlString">Sql語句</param>
/// <returns>返回一個 DataSet</returns>
public static DataSet ExecuteDataSetBySql(string sqlString)
{
return ExecuteBySql<DataSet>(database.ExecuteDataSet, sqlString);
}
/// <summary>
/// 執行Sql語句,返回受影响的行数。
/// </summary>
/// <param name="sqlString">Sql語句</param>
///<returns>返回受影响的行数。</returns>
public static int ExecuteNonQueryBySql(string sqlString)
{
return ExecuteBySql<int>(database.ExecuteNonQuery, sqlString);
}
/// <summary>
/// 執行Sql語句,并返回查询所返回的结果集中第一行的第一列。所有其他的列和行将被忽略。
/// </summary>
/// <param name="sqlString">Sql語句</param>
///<returns>返回结果集中第一行的第一列。</returns>
public static object ExecuteScalarBySql(string sqlString)
{
return ExecuteBySql<object>(database.ExecuteScalar, sqlString);
}
OK,優化完成。滿足代碼高復用的要求,也滿足代碼簡潔性的要求。
其他方法的實現代碼就不貼出,思路基本都一致。可以下載DEMO,全部實現代碼都有。包括測試。測試需要有Northwind數據庫
app.config文件的配置,通過企業庫配置程序配置。
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<dataConfiguration defaultDatabase="Connection String" />
<connectionStrings>
<add name="Connection String" connectionString="Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=sa"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
測試: