ERP项目开发中的DataTable的性能优化 代码写得漂亮看起来舒服,运行起来也有效率
公司的ERP框架是用ORM技术来访问数据库的,但有些查询还是会用DataTable保存数据,并且会把用户修改后的数据保存到服务器中。在习惯了ORM的写法后,对于用DataTable的保存用户修改过的数据,然后保存到数据库中反而有些不适应。ORM会自动检测到哪些数据项被改动了,进而生成必要的UPDATE子句,如果没有数据被更改,则不会产生任何UPDATE语句,这是ORM的好处与便利。把这个技巧应用到DataTable中,来看看下面的性能优化技巧。
DataColumn item = new DataColumn("IsChanged", typeof(bool)); item.DefaultValue = false; itemTable.Columns.Add(item);
有一个临时的查询表itemTable,保存物料的计划信息。在物料计划功能中,我们会修改一下物料的计划数据,然后把它保存到数据库中。因为有很多物料,有的会被修改计划日期,有的不会修改,所以我给物料计划表itemTable加了一个额外的字段IsChanged,以表示这个物料的物料计划是否被修改过。如果被修改过,比如下面的方法
itemTable.Rows[0]["PlanQty"]=200; itemTable.Rows[0]["IsChanged"]=true;
第二行代码,我会把这个table的IsChange列的值设为true,表示这一行已经被修改过,在保存时,需要生成SQL UPDATE语句。这样,在窗体被关闭时或用户点击保存按钮时,用下面的判断语句
int changed=(from item in itemTable.AsEnumerable() where item.Fields<bool>("IsChanged")==true selectg item).Count(); if(changed) { foreach(item in itemTable.AsEnumerable() where item.Fields<bool>("IsChanged")==true) //save item and its plan qty }
changed变量判断当前是否有物料的计划数量被更改过,如果有才保存被改过的物料及其计划,否则不会做任何动作。
以此类推,这个技巧还可以应用于删除或是新增
DataColumn item = new DataColumn("IsNew", typeof(bool)); item.DefaultValue = false; itemTable.Columns.Add(item); item = new DataColumn("IsDeleted", typeof(bool)); item.DefaultValue = false; itemTable.Columns.Add(item);
虽然这是个很小的技巧,却可以解决很多场合的问题。举例说明
1 用户打开物料计划功能,只是看了一下,没有修改任何物料及其计划,在退出功能时,你不应该提示用户保存,因为用户没有作任何数据修改动作。
2 用户新增加了一条物料及其计划,你可以判断是新加的,进而生产INSERT语句,而不是UPDATE语句。如果不用这个技巧,你需要到数据库中去判断是否有这个物料的计划数据,如果有则产生UPDATE语句,否则产生INSERT语句。应用我说的这个技巧(IsNew),你可以明显的减少往返于数据库之间的逻辑,性能会有明显的改善。
3 用户删除了一条物料及其计划,itemTable少了一行,你怎么把它写回到数据库中去呢?应用这个IsDeleted技巧,不对itemTable调用DeleteRow方法,而是把它的IsDeleted设为true,表示这个物料的计划被删除了,需要产生DELETE语句发送到数据库中。
在判断itemTable是否被修改过,也可以应用这个技巧
foreach (DataRow row in itemTable.Rows) { if (row.RowState == DataRowState.Unchanged) continue; //save changed item and its plan qty }
DataRow有一个RowState属性,以表示这个表是否被修改过。你可以不用加上面的IsChanged列而应用RowState来判断,也可以达到这个目的。DataRowState.Added 表示是新增加的一行数据,其它的值是
// Summary: //Gets the state of a System.Data.DataRow object. [Flags] public enum DataRowState { // Summary: // The row has been created but is not part of any System.Data.DataRowCollection. // A System.Data.DataRow is in this state immediately after it has been created // and before it is added to a collection, or if it has been removed from a // collection. Detached = 1, // // Summary: // The row has not changed since System.Data.DataRow.AcceptChanges() was last // called. Unchanged = 2, // // Summary: // The row has been added to a System.Data.DataRowCollection, and System.Data.DataRow.AcceptChanges() // has not been called. Added = 4, // // Summary: // The row was deleted using the System.Data.DataRow.Delete() method of the // System.Data.DataRow. Deleted = 8, // // Summary: // The row has been modified and System.Data.DataRow.AcceptChanges() has not // been called. Modified = 16, }
对于Add或Delete的情况,我还是习惯于加IsNew或IsDeleted列,尽管这不是必要的。
在应用ORM框架保存实体时,它会检测实体的字段属性是否被修改,只有修改过的属性,才会出现在ORM框架生成的UPDATE语句中,这样确实有效率,与判断DataTable的列值是否被修改过相似,看似乎一点点的改进,对于系统的性能提升是有好处的。