【问题标题】:How to minimise OleDbDataAdapter time to fetch data from remote database如何最小化 OleDbDataAdapter 从远程数据库获取数据的时间
【发布时间】:2014-09-10 13:25:48
【问题描述】:

我的 Windows 窗体应用程序包含 OleDbDataAdapter,从远程数据库获取数据需要更长的时间。它无法检索/保存像 5000 行这样的表数据(应用程序被击中)。这是我的代码。

environments = ConfigurationManager.GetSection("Environment") as NameValueCollection;
string strConnString = environments[envs];
conn = new OleDbConnection(strConnString);
conn.Open();
OleDbDataAdapter objDa = new OleDbDataAdapter("select * from tblABC", conn);
DataSet ds1 = new DataSet();
objDa.Fill(ds1);
dataGridView1.DataSource = ds1.Tables[0];

环境部分在 app.config 文件中配置:

<configuration>
  <configSections>
    <section name ="Environment" type="System.Configuration.NameValueSectionHandler" />
  </configSections>

  <Environment>
    <add key ="CIT" value ="Password=pwd123;User ID=abc123;Data Source=db1;Persist Security Info=True;Provider=MSDAORA"/>
    <add key ="SIT" value ="Password=pwd234;User ID=abc234;Data Source=db2;Persist Security Info=True;Provider=MSDAORA"/>
    <add key ="UAT" value ="Password=pwd345;User ID=abc345;Data Source=db3;Persist Security Info=True;Provider=MSDAORA"/>

  </Environment>
</configuration>

如果有人可以用代码提出更好的方法/机制,那就太好了。

【问题讨论】:

  • 究竟发生了什么?您确定您与数据库的连接正常吗?如果您执行“从 .. 中选择前 10 个 *”,它会起作用吗?
  • 我已连接并能够在 DB 上执行命令。 1. 每次执行命令时,我都会看到我的应用程序重新连接到数据库。 2. 我的应用程序在检索更多记录作为结果时消耗更多时间(假设超过 1000 条记录)。需要尽量减少这个时间
  • 即使我对断开连接的架构以及大量与数据相关的支持对象感到满意。但是在几次“实时”实施之后,所有的幸福都失去了。根据我的经验,我自己在使用 ADO.NET 时创建了一些规​​则。 1.永远不要将所有内容加载到数据集中(NO select * from table)。仅选择您需要的列。 2. 如果您知道表中的行数将超过几千行,请以分页方式加载它。 4. 始终使用存储过程,而不是内联查询。 5.使用SSMS,执行计划,优化SP内部的查询。
  • "每次我执行命令时,我都会看到我的应用程序重新连接到 DB。" - 每次使用时都应该关闭连接 - 最好使用“using”语句。
  • 如果您绝对需要所有数据,您可以最初直接获取前 200 行,然后在新线程的后台静默获取其余数据。这应该让您的用户保持参与并且您的 UI 具有交互性。此外,您每次可以检索 200 行的数据块。

标签: c# .net winforms oledb oledbdataadapter


【解决方案1】:

您是否尝试过使用线程。在程序的某处创建一个子函数,如下所示

public void dataPullingThread(){
    try{
        //your connection code goes here like below//
        environments = ConfigurationManager.GetSection("Environment") as NameValueCollection;
        string strConnString = environments[envs];
        conn = new OleDbConnection(strConnString);
        conn.Open();
        OleDbDataAdapter objDa = new OleDbDataAdapter("select * from tblABC", conn);
        DataSet ds1 = new DataSet();
        objDa.Fill(ds1);
        dataGridView1.DataSource = ds1.Tables[0];
        conn.Close();
    }
    catch (Exception e){

    }

}



//call your thread from desired location in program///

using System.Threading;
Thread thread = new Thread (new ThreadStart(dataPullingThread));
thread.start;

//Your application will continuously run; however, the data will appear when ever the thread auto kills itself. You can boost the speed if you create more then one thread. That means each thread selecting different rows of the database, I hope this information will help you//

【讨论】:

  • 我们如何创建不同的线程来选择数据库的不同行?
【解决方案2】:

以下是一些通用的 ADO.NET 优化技巧:

  • 请确保您确实需要所有字段,而不是SELECT *。问题是可能会检索到许多未使用的字段值并消耗资源。

例如,如果您的表包含的字段超过这三个字段,请使用 SELECT Field1, Field2, Field3 而不是 SELECT *

  • 坚持以下连接打开/关闭模式:

例子:

using(var con = new OleDbConnection(strConnString))
{
    con.Open();

    ...

    con.Close();
}

所以即使发生错误的事情也会关闭连接,并在服务器端使用connection pooling机制。

  • DbDataReader 对象要快得多。请尝试使用 DbDataReader 而不是 DbDataAdapter。使用它来填充一个通用列表,然后将您的 DataGrid 绑定到该列表。

但是,您的连接本身似乎有问题。您如何确定应用程序正在获取数据或尝试建立连接?要检查这一点,请将您的查询更改为非常快的查询,例如“select sysdate from dual”,以检查问题是否来自连接尝试。

【讨论】:

  • 我很确定应用程序已连接到数据库。我已经调试并检查了连接状态并运行了一些命令,包括“Select sysdate from dual”。让我试试 DbDataReader - Hope Works
  • 我看到您正在连接到 Oracle 数据库。您可能想看看是否可以一次返回较小的数据子集,例如 5 x 1000 条记录,看看是否有帮助。您可能还想查看您从中获取数据的表上的索引,以确保您的 SELECT WHERE 语句正在使用该索引(如果表非常大)。
  • 我们如何返回一小部分数据以显示在 dataGridView 上?你的意思是分页概念吗?如果不分页,您能否提供一些代码来返回较小的数据子集 - 会很有帮助
  • 您对 DbDataReader 的建议在一定程度上奏效了。谢谢@Larry
  • ODP.Net 有一些批量获取数据的选项,您也可以设置 Fetch Size,这将确保您可以在后台以块的形式获取数据。它有助于优化读取操作
猜你喜欢
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多