在维护一个老项目过程中,为了愉快的使用 dapper 从datatable中获取要批量操作的数据而不用再手动写一堆匿名对象集合,所以写了个下面的静态方法,用来支持dapper的写数据库方法。记录一下以免以后做重复工作。直接上代码:
/// <summary>
/// 将DataTable 转成 List<dynamic>,主要用于给dapper批量操作时传参数。
/// </summary>
/// <param name="table">要转换的DataTable对象</param>
/// <param name="filterFields">要筛选的列。默认不传,此时返回全部列</param>
/// <param name="includeOrExclude">指定上一个参数条件是要保留的列还是要排除的列</param>
/// <returns></returns>
public static List<dynamic> ToDynamicList(this DataTable table, string[] filterFields = null, bool includeOrExclude = true)
{
var modelList = new List<dynamic>();
var isFilter = filterFields != null && filterFields.Any();
IEnumerable reservedColumns = table.Columns;
if (isFilter)
reservedColumns = table.Columns.Cast<DataColumn>().Where(c => filterFields.Contains(c.ColumnName) == includeOrExclude);
foreach (DataRow row in table.Rows)
{
dynamic model = new ExpandoObject();
var dict = (IDictionary<string, object>)model;
foreach (DataColumn column in reservedColumns)
{
dict[column.ColumnName] = row[column];
}
modelList.Add(model);
}
return modelList;
}
然后,在操作Dapper 批量的增、删除、改 数据库表中的数据时,就可以这样从dataTable获取数据:
bool commitOK = false;
using (IDbConnection con = new System.Data.SqlClient.SqlConnection(constr))
{
if (con.State == ConnectionState.Closed)
con.Open();
IDbTransaction transaction = con.BeginTransaction();
var strInsert = $"insert into PriceStrategy(item_clsno, model, color, jhPrice, pfPrice) values(@item_clsno, @model, @color, @jhPrice, @pfPrice)";
var strUpdate = $"update PriceStrategyset model=@model, color=@color, jhPrice=@jhPrice, pfPrice=@pfPrice,updatedTime=getdate() where id=@id";
var strDelete = $"delete PriceStrategywhere id=@id";
if (dataTable.GetChanges(DataRowState.Added)?.Rows?.Count > 0)
await con.ExecuteAsync(strInsert, dataTable.GetChanges(DataRowState.Added).ToDynamicList(new [] { "item_clsno", "model", "color", "jhPrice", "pfPrice" }), transaction);
if (dataTable.GetChanges(DataRowState.Modified)?.Rows?.Count > 0)
await con.ExecuteAsync(strUpdate, dataTable.GetChanges(DataRowState.Modified).ToDynamicList(new [] { "id", "model", "color", "jhPrice", "pfPrice" }), transaction);
if (dataTable.GetChanges(DataRowState.Deleted)?.Rows?.Count > 0)
await con.ExecuteAsync(strDelete, dataTable.GetChanges(DataRowState.Deleted).ToDynamicList(new [] { "id" }), transaction);
try
{
transaction.Commit();
commitOK = true;
}
catch
{
transaction.Rollback();
throw;
}
}
if (commitOK)
{
MessageBox.Show(this, "保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
上面代码中的三个调用都使用了静态方法的列筛选,如果你的项目是小数据量、不太多的列则上面的方法在不考虑性能的情况下完全可以粗暴的改为直接.ToDynamicList() 即把整个datatable的所有列都转成List<dynamic>集合,完全没有问题。
这样操作比 Ado.Net 时代确实跨进了一步。当然现代开发都流行使用 EntityFrameworkCore 等功能更强大的ORM工具。如果你像我一样是在维护一些老项目,希望本篇博文对你有帮助,别忘记点个赞。