之所以想到要将这两个结合起来,是因为这两个东东都有各自的优势:
Ibatis:了解Ibatis的人都知道,它最让人觉得强大的地方在于参数以及查询结果与实体类的映射。这样我们省去了拼接sql的麻烦,将sql语句与代码分离。同时ibatIs通过<IsNotEmpty>等标签实现了动态sql。这些让我们的代码看上去整洁优雅多了。但是它有一个不足的地方,对批量处理的实现不是很好。比如要页面上有一个grid,用户一通增删改后批量提交,这个时候我们就想起了SqlDataAdapter的update功能了。
SqlDataAdapter:至少对我来说,批量更新是最大的亮点,不论是效率还是实现难易度都比ibatis要好多了,但是传统使用SqlDataAdapter都把sql写在代码里面,显得还挫的说。所以在这个时候我就想到能不能用Ibatis获取sql语句,然后用SqlDataAdapter执行批量更新。
获取ibatis映射后的sql语句,问百度查google,查到的如下方法:
public static string GetSql(string statementName, object paramObject)
{
string result = string.Empty;
paramMap = null;
if (Mapper == null) return result;
try
{
IMappedStatement statement = Mapper.GetMappedStatement(statementName);
if (!Mapper.IsSessionStarted)
{
Mapper.OpenConnection();
}
RequestScope scope = statement.Statement.Sql.GetRequestScope(statement, paramObject, Mapper.LocalSession);
result = scope.PreparedStatement.PreparedSql;
}
catch (Exception ex)
{
result = "Error for obtaining sql string:" + ex.Message;
}
finally
{
Mapper.CloseConnection();
}
return result;
}
但是可惜的是这个方法只能得到未代入参数的sql语句,如select * from a where id = @param0这种形式的,下一步是要将实体类中的参数值传入其中。这里我联想到可以ADO中的SqlParameter,只要将实体类中的参数值与@param0对应起来,问题就解决了。所以赶紧看看Statement中是否有参数的信息,发现其中的ParameterMap正是Ibatis解析sql得到的实体类参数列表,这样问题都清除了。最后的代码:
public static string GetSql(string statementName, object paramObject, out ParameterMap paramMap)
{
string result = string.Empty;
paramMap = null;
if (Mapper == null) return result;
try
{
IMappedStatement statement = Mapper.GetMappedStatement(statementName);
if (!Mapper.IsSessionStarted)
{
Mapper.OpenConnection();
}
RequestScope scope = statement.Statement.Sql.GetRequestScope(statement, paramObject, Mapper.LocalSession);
result = scope.PreparedStatement.PreparedSql;
paramMap = statement.Statement.ParameterMap;
}
catch (Exception ex)
{
result = "Error for obtaining sql string:" + ex.Message;
}
finally
{
Mapper.CloseConnection();
}
return result;
}
/// <summary>
/// 利用ibatis取得sql,同时将参数代入其中,执行得到相应的SqlDataAdapter和DataTable
/// </summary>
/// <param name="statementId"></param>
/// <param name="paramterObject"></param>
/// <param name="sqlAdap"></param>
/// <returns></returns>
public static DataTable ExecuteForDateTable(string statementId, object paramterObject, ref SqlDataAdapter sqlAdap)
{
ParameterMap paramMap = null;
string sqlstr = GetSql(statementId, paramterObject, out paramMap);
DataTable dataTable = new DataTable();
string sqlConnectionString = IbatisMapper.Mapper.DataSource.ConnectionString;
SqlConnection sqlConnection = new SqlConnection(sqlConnectionString);
SqlCommand sqlCommand = new SqlCommand(sqlstr, sqlConnection);
if (paramMap != null)
{
for (int i = 0; i < paramMap.Properties.Length; i++)
{
SqlParameter sp = new SqlParameter("@param" + i, paramterObject.GetType().
GetProperty(paramMap.Properties[i].PropertyName).GetValue(paramterObject, null));
sqlCommand.Parameters.Add(sp);
}
}
sqlAdap = new SqlDataAdapter(sqlCommand);
SqlCommandBuilder sqlBuilder = new SqlCommandBuilder(sqlAdap);
sqlConnection.Open();
sqlAdap.Fill(dataTable);
sqlConnection.Close();
return dataTable;
}
至于批量更新,
SqlDataAdapter.Update()
方法相信大家已经很熟悉了。
研究了一晚上才研究出来,再次左下记录,也希望对大家有用处。