随笔 - 37  文章 - 0  评论 - 164 
  2011年11月25日

       网上合并DataTable通用方法的文章很多,结合项目开发中的常用需求,并借鉴网上的做法,写了一个合并DataTable的通用方法,主要功能是合并两个DataTable(结构可以不同,如字段不完全一致),并可以根据某一列值进行排重处理。代码如下:

View Code
        ///<summary>   
/// 将两个列不同的DataTable合并成一个新的DataTable
///</summary>
///<param name="dt1">源表</param>
///<param name="dt2">需要合并的表</param>
///<param name="primaryKey">需要排重列表(为空不排重)</param>
///<param name="maxRows">合并后Table的最大行数</param>
///<returns>合并后的datatable</returns>
public static DataTable MergeDataTable(DataTable dt1, DataTable dt2, string primaryKey, int maxRows)
{
//判断是否需要合并
if (dt1 == null && dt2 == null)
{
return null;
}
if (dt1 == null && dt2 != null)
{
return dt2.Copy();
}
else if (dt1 != null && dt2 == null)
{
return dt1.Copy();
}
//复制dt1的数据
DataTable dt = dt1.Copy();
//补充dt2的结构(dt1中没有的列)到dt中
for (int i = 0; i < dt2.Columns.Count; i++)
{
string cName = dt2.Columns[i].ColumnName;
if (!dt.Columns.Contains(cName))
{
dt.Columns.Add(new DataColumn(cName));
}
}
//复制dt2的数据
if (dt2.Rows.Count > 0)
{
Type t = dt2.Rows[0][primaryKey].GetType();
bool isNeedFilter = string.IsNullOrEmpty(primaryKey) ? false : true;
bool isNeedQuotes = t.Name == "String" ? true : false;
int mergeTableNum = dt.Rows.Count;
for (int i = 0; i < dt2.Rows.Count && mergeTableNum < maxRows; i++)
{
bool isNeedAdd = true;
//如果需要排重时,判断是否需要添加当前行
if (isNeedFilter)
{
string primaryValue = dt2.Rows[i][primaryKey].ToString();
string fileter = primaryKey + "=" + primaryValue;
if(isNeedQuotes)
{
fileter = primaryKey + "='" + primaryValue + "'";
}
DataRow[] drs = dt.Select(fileter);
if (drs != null && drs.Length > 0)
{
isNeedAdd = false;
}
}
//添加数据
if (isNeedAdd)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < dt.Columns.Count; j++)
{
string cName = dt.Columns[j].ColumnName;
if (dt2.Columns.Contains(cName))
{
//防止因同一字段不同类型赋值出错
if (dt2.Rows[i][cName] != null && dt2.Rows[i][cName] != DBNull.Value && dt2.Rows[i][cName].ToString() != "")
{
dr[cName] = dt2.Rows[i][cName];
}
}
}
dt.Rows.Add(dr);
mergeTableNum++;
}
}
}
return dt;
}



posted @ 2011-11-25 22:04 陈晨 阅读(107) 评论(0) 编辑
  2011年10月30日
摘要: 分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系统中取出每个学科前3名的学生。这种查询在SQL Server 2005之前,写起来很繁琐,需要用到临时表关联查询才能取到。SQL Server 2005后之后,引入了row_number()函数,row_number()函数的分组排序功能使这种操作变得非常简单。阅读全文
posted @ 2011-10-30 10:06 陈晨 阅读(283) 评论(1) 编辑
  2011年9月26日

      问题缘起:收到运维同事发来的邮件,说自上次网站更新后,CPU使用率上升趋势明显(下图中红框部分所示),但网站访问数并没有增加。

     

      问题排查:是什么原因导致CPU使用率上升呢?肯定是某个访问量比较大的页面进行了耗CPU的操作,如文件读写、内存中的一些复杂运算等。结合上次网站更新内容,将问题锁定在了房源详情页。主要涉及到读xml文件(最大的有2M多)到DataTable中,每次打开页面时根据DataTable中的两个列值判断在这个DataTable中有没有,比较严重的是读文件没加缓存,造成了频繁的读文件,使CPU一直处于忙碌状态。

      找到了问题所在,修改起来就容易多了,增加缓存就好了,下面是修改后的伪代码。修改之后更新网站,CPU使用率又恢复到正常值了(红框后面的部分)。

简单代码示例
    /// <summary>
/// 获取置业专家列表
/// </summary>
/// <returns>置业专家列表</returns>
public static DataTable GetAgentXML()
{
DataTable dt = null;
string cacheName = "agentall_zyzj";
if (CacheManager.IsCached(cacheName))
{
object o = CacheManager.GetCache(cacheName);
if (o != null)
{
dt = o as DataTable;
}
}
if (dt == null)
{
//读取xml文件到DataTable中
dt = GetAgentXMLFromFile();
if (dt != null)
{
try
{
if (dt.Rows.Count > 0)
{
dt.PrimaryKey = new DataColumn[] { dt.Columns["newcode"], dt.Columns["agentid"] };
}
}
catch
{ }
CacheManager.InsertCache(cacheName, dt, System.DateTime.Now.AddMinutes(60));
}
}
return dt;
}
/// <summary>
/// 判断是否为置业专家
/// </summary>
/// <returns>是否为置业专家</returns>
public static bool CheckZyzj(long agentID, long newCode)
{
DataTable Agentdt = new DataTable();
bool isZyzj = false;
try
{
Agentdt = GetAgentXML();
if (Agentdt != null && Agentdt.Rows.Count > 0)
{
DataRow[] drs = Agentdt.Select(" agentid=" + agentID + " and newcode=" + newCode);
if (drs != null && drs.Length > 0)
{
isZyzj = true;
}
}
}
catch (Exception ex)
{
isZyzj = false;
}
return isZyzj;
}

      需要特别说明的一点,此次优化在增加缓存的同时,还做了一个小调整,将数据从xml文件读到DataTable后,为DataTable设置了主键“dt.PrimaryKey = new DataColumn[] { dt.Columns["newcode"], dt.Columns["agentid"] }”,为DataTable设置主键可以大大提高select查询效率(这点有些类似于数据库中表的主键)。因为这次修改了两个地方,增加主键的效率不好用数据说明。但之前做过一个复杂报表的生成,在内存中要对DataTable做大量查询,简单的增加主键后,效率提升了七八倍。

      缓存在编程中至关重要,网站访问量小时缓存与否影响不大,一旦量上来了,再简单的逻辑也需要多考虑,平日里要多有些思想意识在里头,才会有预见性,减少上线后出现问题的几率。

posted @ 2011-09-26 23:14 陈晨 阅读(1983) 评论(12) 编辑
  2011年5月8日
摘要: 有时候,我们项目做多了,尤其是网站项目做多了,就会觉得基础知识好像没多大用,但殊不知,对一些基础概念理解不深,就会带来问题。整理下项目中因为基础概念理解不深造成的问题,希望能给以启发。阅读全文
posted @ 2011-05-08 09:53 陈晨 阅读(225) 评论(0) 编辑
  2011年1月12日
摘要: IE下打开网页时,会弹出“Stack overflow at line: 0”的弹框。经分析,这个bug是由于img标签的onerror事件引起的。程序中用到的代码片段如下:正常情况下显示src所指路径的图片,加载失败时显示通过img标签的onerror事件显示另一张图片,问题就出现在了这里,当另一张图片也不存在时,就造成了循环触发onerror事件,在IE下就会弹出“stack overflow”的弹框。阅读全文
posted @ 2011-01-12 21:14 陈晨 阅读(418) 评论(0) 编辑
  2010年11月14日
摘要: 表变量存储在内存中,而临时表存储在tempdb中,会涉及到物理IO读写,那么我们是否可以由此得出结论,使用表变量要比使用临时表效率高呢?相信有一部分人会和我有同样的想法,使用表变量的效率高,真是如此吗?先从一次优化存储过程的经历说起。 阅读全文
posted @ 2010-11-14 11:43 陈晨 阅读(389) 评论(0) 编辑
  2010年11月8日
摘要: 通过添加Web引用的方式,让.NET编译器帮我们生成服务代理,然后调用对应的Web服务,这种方式最简单,但却和Web服务的地址、方法名、参数全都绑定在了一起,如果Web服务的方法或者是参数发生改变,就需要重新添加引用,使用起来不大方便,于是想到了动态创建调用WebService。阅读全文
posted @ 2010-11-08 00:40 陈晨 阅读(473) 评论(5) 编辑
  2010年11月2日
摘要: 一个简单的SQL语句:select count(1) from tableName with(nolock) where columnA=A and columnB=B and columnC=C,被一个关键页面调用,虽然加了Memcache缓存,但由于数据结构设计问题,造成了数据库服务器CPU负载高达100%,关键页面响应超时,造成极其不好的影响。 究其原因,缺少索引,数据结构设计之初,没有为该...阅读全文
posted @ 2010-11-02 08:05 陈晨 阅读(553) 评论(2) 编辑
  2010年10月2日
摘要: 一直很喜欢用李天平的“动软.Net代码生成器”,界面简洁、操作简单,用来开发辅助生成代码和生成Word文档,大大提高效率。唯一不喜欢的是实体层变量命名方式采用了变量用“_”+数据库字段名方式,属性名采用数据库字段名方式,个人更喜欢用变量首字母小写属性首字母大写的方式。国庆假期闲来无事,决定改造下生成实体层的方法,让其按照自己的习惯来命名,感谢李天平对代码生成器的开源,才使这次改造成为可能。 阅读全文
posted @ 2010-10-02 00:51 陈晨 阅读(466) 评论(5) 编辑
  2010年7月18日
摘要: 枚举类型无疑给我们开发带来了很大的方便,智能感应+代码可读性就让我们有足够的理由在项目开发中使用枚举类型。但枚举类型使用不当也存在着温柔陷阱,而且陷阱很难发现,让我们一点一点解开隐藏在枚举类型背后的陷阱。阅读全文
posted @ 2010-07-18 11:14 陈晨 阅读(2034) 评论(15) 编辑
  2010年7月17日
摘要: 本篇将以上一篇中计算个人所得税的示例为例,详细介绍Remoting的基础知识,包括远程对象、通道、对象激活方式等。 1.远程对象 分布式计算需要远程对象,客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是获得它的引用。远程对象具有分布式的标识,因此,对对象的引用可以传递到客户端,而引用仍访问同一对象,代理对象知道远程对象的标识。 远程对象必须继承自System.MarshalByRefO...阅读全文
posted @ 2010-07-17 22:42 陈晨 阅读(175) 评论(0) 编辑
  2010年6月22日
摘要: SQL Server 2005的Row_Number() over(order by)排序和where后的order by排序产生的排序规则并不完全相同,我们不能简单的将二者等同起来,结合在一起使用可能会造成意想不到的bug。阅读全文
posted @ 2010-06-22 00:07 陈晨 阅读(573) 评论(5) 编辑
  2010年3月27日
摘要: 老哥公司招人面试,问我愿不愿意过去旁听,当然愿意了,难得的学习机会。总结起来,老哥在面试过程中关注以下几个方面:第一,人品的好坏,人要踏实不能浮躁;第二,Java技术,主要关注的是Structs框架,问到一些细节如标签;第三,是否熟习Linux操作系统,这个要求不高,只要会配置数据库会配置开发环境就差不多了;第四,软件设计理念,软件设计的工具方法,数据库建模的工具方法,会不会书写开发文档,其实这个...阅读全文
posted @ 2010-03-27 20:42 陈晨 阅读(199) 评论(1) 编辑
  2009年12月20日
摘要: 执行SQL语句采用拼接字符串的形式,减运算符和负号连在一起成了SQL的注释符号,把更新时的where条件给注释掉了,真是一个危险的操作!阅读全文
posted @ 2009-12-20 12:19 陈晨 阅读(466) 评论(1) 编辑
  2009年6月18日
摘要: 在.NET中使用OpenFlashChart控件显示图表时,谁会想到图表显示正常与否竟然和服务器IIS是否启用了Gzip压缩有关呢?阅读全文
posted @ 2009-06-18 23:04 陈晨 阅读(706) 评论(2) 编辑