需求

一切都是空的,除了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. Visual Studio IIS Express 不支持.json后缀的mime类型

    vs默认web调试工具中并不支持.json后缀的mime类型. 如何解决,两个方案: 局部单应用:web.config: <system.webServer> .... <stati ...

  2. SQL Server 2005 发布 订阅 (配置实例[图])(转载)

    2.1          发布&订阅 1.       测 试环境: Item 发布机 A 订阅机 B OS Windows 2003 Server Windows 2003 Server S ...

  3. linux查看内核版本、系统版本、系统位数(32or64)

     linux查看内核版本.系统版本.系统位数(32or64) 2011-05-01 22:05:12 标签:linux 内核版本 休闲 系统版本 系统位数 1. 查看内核版本命令: 1) [root@ ...

  4. C++中的异常处理(二)

    C++中的异常处理(二) 标签: c++C++异常处理 2012-11-24 20:56 1713人阅读 评论(2) 收藏 举报  分类: C++编程语言(24)  版权声明:本文为博主原创文章,未经 ...

  5. c# 继承,多态,new /overrid 区别, 引用父类的方法

    好久没碰c#了,偶尔需要制作点小工具.为了一个灵活的架构设计,需要对继承/多态有比较深刻的理解. 不料忘得差不多了,好吧,再来回忆下.直接上代码了,如下: using System; using Sy ...

  6. selenium webdriver的各种driver

    selenium官方加上第三方宣布支持的驱动有很多种:除了PC端的浏览器之外,还支持iphone.Android的driver:大概记录一下selenium支持的各种driver的用途与说明. sel ...

  7. 基础知识《五》---Java多线程的常见陷阱

    1.在构造函数中启动线程 我在很多代码中都看到这样的问题,在构造函数中启动一个线程,类似这样: public class A{ public A(){ this.x=1; this.y=2; this ...

  8. 基础知识《二》java的基本类型

    一.java基本数据类型 Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte.short.int.long.float.double.数值类型 ...

  9. 查看Eclipse中的jar包的源代码:jd-gui.exe

    前面搞了很久的使用JAD,各种下载插件,最后配置好了,还是不能用,不知道怎么回事, 想起一起用过的jd-gui.exe这个工具,是各种强大啊!!! 只需要把jar包直接扔进去就可以了,非常清晰,全部解 ...

  10. Java面向对象的多态

    Java中多态的概念是面向对象中除封装和继承外非常重要的知识点,也是Java面向对象三大特性最后一个特性 多态其实就是指对象存在的多种形态,多态分为引用多态和方法多态 引用多态的含义就是:父类的引用可 ...