需求

一切都是空的,除了Money,只有需求才是最真的,你懂的。

最近接到个略显棘手的需求,思索再三,想出两种方法,可觉得都不太好,这里与大家讨论一下。

需求如下:

用户需要在现有的某个grid中添加新的一列: Des。现有grid的所有数据DataTable:OraDt都来自一个oracle数据库,而新加的Des值却来自别的四个sqlserver数据库中的某一个。四个SqlServer数据库CHNDB,JPNDB,USDB,CANDB的结构相同,只是数据不同。

根据两个变量:geo和desID可以从前面sql DB中中得到Des的值。geo确定从哪个sql数据库中获取,desID用来得到des的值。 geo和desID就在OraDt中存着,如何才能高效的获取des的值?

geo与sqlserver db对应关系如下:

Geo值 Sqlserver DB
CHN  CHNDB
 JPN  JPNDB
 US  USDB
 CAN  CANDB

解决思路

  1. 从Oracle数据库的某表中查询数据,得到DataTab:OraDt;
  2. OraDt中添加新列: DataColumn("Des", typeof(string));
  3. 遍历OraDt的每一个datarow,取得不同的geo和desID的值;
  4. 根据geo和desID的值确定Sqlserver DB并获得des的值;
  5. 更新OraDt中新列row["Des]的值

解决方案伪代码

  • 这种方法思路比较简单,老老实实遍历OraDt的每一个datarow,取得不同的geo和desID的值,然后从对应的sqlser数据库中获取des的值:
  //得到oracle datatable,添加row[des],遍历datatable,获取des的值,更新des
protected void ProcessDataTable()
{
//添加新列
_ds.Tables[0].Columns.Add(new DataColumn("Des", typeof(string)));
string desID = string.Empty;
string geo = string.Empty; //遍历OraDt
foreach (DataRow row in _ds.Tables[0].Rows)
{
if (row["desID"] != DBNull.Value)
desID = row["desID"].ToString(); if (!string.IsNullOrEmpty(desID) )
{
//得到geo
switch (row["countryId"].ToString())
{
case Country.US:
geo = "US";
break;
case Country.China:
geo = "CHA";
break;
case Country.Canada:
geo = " CAN";
break;
case Country.Jpan:
geo = "JPN";
break;
}
//得到添加des
row["Des"]= GetExemptionDes(geo, desID);
}
else row["Des"] = string.Empty;
}
}

 GetExemptionDes的代码:

        private string GetExemptionDes(string geo, string desid)
{
string description = string.Empty;
string query = "select des from taxDes where desid="+desid;
//确定哪个DB获取数据
Database DbGEO = DbGEOFactory.CreateDatabase(geo);
System.Data.Common.DbCommand sqlCmd = DbGEO.GetSqlStringCommand(query);
//获得des值
using (IDataReader dr = DbGEO.ExecuteReader(sqlCmd))
{
while (dr.Read())
{
if (dr["des"] != null)
description = dr["des"].ToString();
}
dr.Close();
}
return description;
} 

性能探究:

这种想法思路简单,问题也显而易见,虽然通常情况下OraDt只有十几个row,可极个别时候OraDt的row能达到上千个,这时候,上面的方法要连续访问 Sqlserver DB上千次,显然严重影响了性能。有某有其他的好方法呢?

第二方案,或者其他更好的解决方法?

由于geo最多只有四个,所以我们可以把相同geo下的desID拼接起来,最后一块访问sqlserver db,这样最多只需要访问四次,思路:

前三步与上面方法一样,

4.根据geo把desid拼接于一个string变量中

5.最后一起访问sqlserver db

6.获得des值,

7.OraDt更新des

第二方法缺憾:

大量datatable的操作实际上也影响了代码的效率,而且OraDt的数据量通常只有几十行,用这种方法处理普通的OraDt时候显然太过繁琐。

可是现在看来似乎只有这两种方法来解决这个问题了,难道真的就由这么个性能问题存在于我们的代码中么?哪位如果有什么新的解决思路,可以一起分享一下,一起进步。

第一种方法和第二种到底用哪一种好呢?

现将第二方案的详细代码列示如下,由于写的匆忙,还未来的及调试,有什么问题或者哪里可以改进,希望大家多多指正。

可以看到这种方法繁琐操纵OraDt,尤其是在方法UpdateOraDT中,由于某种原因不能使用Linq 来连接datatable,三个foreach 嵌套起来简直不堪入目。处理普通的OraDt时候明显会带来性能问题:

protected  void ProcessDataTable()
{
_ds.Tables[].Columns.Add(new DataColumn("ExemptionDes", typeof(string))); string desID = string.Empty;
string geo = string.Empty; //建造一个锯齿数组,[0]:geo,[1]: 该geo是否需要被访问,默认0表示不需要,[3]用来拼接desID
string[][] geoExistArray = new string[][] {
new string[] { "NA", "","" },
new string[] { "LA", "","" },
new string[] { "EMEA", "","" },
new string[] { "AP", "","" },
};
//遍历datatable
foreach (DataRow row in _ds.Tables[].Rows)
{
if (row["desID"] != DBNull.Value)
{
xmtn_ID = row["desID"].ToString();
} //如果desID为空,直接将des设置为0
//不为空,则遍历datatable,取des值
if (!string.IsNullOrEmpty(desID))
{
switch (row["countryId"].ToString()) {
case Country.US:
geo = "US";
geoExistArray[][] = "";
geoExistArray[][] = geoExistArray[][] + desID+ ",";
break;
case Country.China:
geo = "CHN";
geoExistArray[][] = "";
geoExistArray[][] = geoExistArray[][] + desID+ ",";
break;
case Country.Canada:
geo = "CAN";
geoExistArray[][] = "";
geoExistArray[][] = geoExistArray[][] + desID+ ",";
break;
case Country.Jpan:
geo = "JPN";
geoExistArray[][] = "";
geoExistArray[][] = geoExistArray[][] + desID+ ",";
break;
}
}
else row["Des"] = string.Empty;
} //移除每个拼出的desID字符串中的最后一个逗号
foreach (var array in geoExistArray)
{
if (array[].Length > )
array[].Remove(array[].Length - , );
}
//获取des值并更新OraDT
UpdateOraDT(_ds.Tables[], geoExistArray);
}

UpdateOraDT代码:

        private DataTable UpdateOraDT(DataTable dt, string[][] geoExistArray)
{
DataTable ExemDesDT;
foreach (var GeoArrary in geoExistArray)
{
//得出一个需要被访问的sql db下的所有des,存于ExemDesDT
if (GeoArrary[1] == "1")
{
ExemDesDT = GetExemptionDesSQL(GeoArrary[0], GeoArrary[2]);
if (ExemDesDT != null)
//遍历ExemDesDT,如果ExemDesDT中的id_exemption等于OraDt中的desID ,则获取des
foreach (DataRow pyrow in ExemDesDT.Rows)
{
foreach (DataRow phxrow in dt.Rows)
{
if (pyrow["id_exemption"] == phxrow["desID"])
phxrow["ExemptionDes"] = pyrow["description"].ToString());
}
}
}
}
return dt;
}

  

GetExemptionDesSQL方法:
       private DataTable GetExemptionDesSQL(string geo, string desidList)
{
DataTable ExemDesDT = new DataTable();
string query = " select des from taxDes where desid in (" + desidList+")";
Database DbGEO = DbGEOFactory.CreateDatabase(geo);
System.Data.Common.DbCommand sqlCmd = DbPyramid.GetSqlStringCommand(query);
ExemDesDT = DbGEO.ExecuteDataSet(sqlCmd).Tables[];
return ExemDesDT;
}

思考探索,如何才能高效访问我的这个DataTable?的更多相关文章

  1. 关于socket通讯,如何才能高效?

    关于socket通讯,如何才能高效? 网络通讯,一个不朽的话题,今天和一个做游戏的朋友(以前的同事聊天),他向我诉说了他的痛苦 他之前是做客户端的,无奈人力资源紧张,也开始搞服务器,他说自己的服务器总 ...

  2. MySQL 开启与关闭远程访问&&授权前需执行GRANT USAGE ON *.* TO 'cai'@'%' IDENTIFIED BY 'caigan2015';才能终端访问

    MySQL 开启与关闭远程访问 (1)通过MySQL用户去限制访问 权限系统目的: MySQL基于安全考虑root账户一般只能本地访问,但是在开发过程中可能需要打开root的远程访问权限,今天介绍的就 ...

  3. 我用的php开发环境是appserv一键安装,通过http://localhost测试成功,但是我有点不清楚的就是为什么访问.php文件要在地址栏上加上localhost(即http://localhost/text.php)才能成功访问?

    这类似于一个域名地址. 因为默认localhost 就是指向本机.所以就用这个来访问自己本地的网页.比如你也可以输入 http://127.0.0.1/text.php http://192.168. ...

  4. 配置linux 防火墙,只有固定IP和端口才能能访问完美解决

    //添加开放的端口和固定ip vi  /etc/sysconfig/iptables [root@root220156 /]# echo "unset MAILCHECK"> ...

  5. 怎样才能高效地使用JQuery

    1. 使用最新版本的jQuery jQuery的版本更新很快,你应该总是使用最新的版本.因为新版本会改进性能,还有很多新功能.下面就来看看,不同版本的jQuery性能差异有多大.这里是三条最常见的jQ ...

  6. C#高效导出Excel(IList转DataTable,DataSet)

    微软的Excel操作类导出Excel会很慢,此方法简单的把表中内容以字符串的形式写入到Excel中,用到的一个技巧就是"\t". C#中的\t相当于Tab键,写入到Excel中时就 ...

  7. nginx配置访问密码,让用户输入用户名密码才能访问

    如果我们在 nginx 下搭建了一些站点,但是由于站点内容或者流量的关系,我们并不想让所有人都能正常访问,那么我们可以设置访问认证.只有让用户输入正确的用户名和密码才能正常访问.效果如下: 在 ngi ...

  8. ASP.NET MVC 随想录——探索ASP.NET Identity 身份验证和基于角色的授权,中级篇

    在前一篇文章中,我介绍了ASP.NET Identity 基本API的运用并创建了若干用户账号.那么在本篇文章中,我将继续ASP.NET Identity 之旅,向您展示如何运用ASP.NET Ide ...

  9. 解决Flex4 发布后访问 初始化极其缓慢的问题

    原文http://blog.163.com/vituk93@126/blog/static/170958034201282222046364/ 昨天找了个免费.net空间,想测试一下做的一个简单Fle ...

随机推荐

  1. 工具分享——将C#文档注释生成.chm帮助文档

    由于最近需要把以前的一个项目写一个文档,但一时又不知道写成怎样的,又恰好发现了可以生成chm的工具,于是乎我就研究了下,感觉还不错,所以也给大家分享下.好了,不多废话,下面就来实现一下吧. 生成前的准 ...

  2. 神经网络训练中的Tricks之高效BP(反向传播算法)

    神经网络训练中的Tricks之高效BP(反向传播算法) 神经网络训练中的Tricks之高效BP(反向传播算法) zouxy09@qq.com http://blog.csdn.net/zouxy09 ...

  3. 旋转屏幕时,假如自定义的xib大小变了,可能是这个属性没有修改

    虽然xib内部启用了自动布局,但是当xib放入外界,xib自身的autoresizing是存在的

  4. pyenv 以及 virtualenv

    244 pyenv global 3.5.1 245 which python 246 python 247 pip install virtualenv 248 ls 249 pwd 250 ls ...

  5. go tool proof

    echo list | go tool pprof -alloc_space gateway http://10.2.1.93:8421/debug/pprof/heap > abc.log e ...

  6. linux kernel thread(Daemons)

    内核线程是直接由内核本身启动的进程.内核线程实际上是将内核函数委托给独立的进程,与系统中其他进程“并行”执行(实际上,也并行于内核自身的执行),内核线程经常被称为内核“守护进程”.它们主要用于执行下列 ...

  7. ubuntu查看版本命令

    有两种方法 1,cat /etc/issue 2,sudo lsb_release -a 这个查询出来的结果比上面的那个全一些.

  8. [转]linux awk命令详解

    原文链接 : http://blog.chinaunix.net/uid-23302288-id-3785105.html   awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢 ...

  9. 搭建DNS服务器

    导读 Linux下架设DNS服务器通常是使用Bind程序来实现的.Bind是一款实现DNS服务器的开放源码的软件.DNS即域名系统,主要功能是将人们易于记忆的Domain Name(域名)与不易记忆的 ...

  10. Unity3D 4.x 使用Mecanim实现连击

    http://blog.csdn.net/onerain88/article/details/12854817 Unity3D 4.x 版本之后提供了一种新的动画机制Mecanim,虽然目前还支持之前 ...