代码之家  ›  专栏  ›  技术社区  ›  Colin Pickard

在ASP.NET中查询多个数据库的好方法

  •  0
  • Colin Pickard  · 技术社区  · 16 年前

    我已经拼凑了一些有用的东西,但不幸的是,它非常慢。我认为,十几个数据库中至少有一个总是无法访问或处于错误状态,这一事实加剧了这种情况。

    除了速度慢之外,我还忍不住认为这不是最好的方式,也不是很像.NET。

    <tr> ,并且对于给定的查询,它的运行速度至少是原来的两倍。但我真的不高兴,我想提高我的知识!

    public void BindData(string mySQL)
        {
            OracleConnection myConnection;
            OracleDataAdapter TempDataAdapter;
            DataSet MainDataSet = new DataSet();
            DataTable MainDataTable = new DataTable();
            DataSet TempDataSet;
            DataTable TempDataTable;
            string connectionString = "";
            Label1.Visible = false;
            Label1.Text = "";
    
            foreach (ListItem li in CheckBoxList1.Items)
            {
                if (li.Selected)
                {
                    connectionString = "Data Source=" + li.Text + "";
                    connectionString += ";Persist Security Info=True;User ID=user;Password=pass;Unicode=True";
                    myConnection = new OracleConnection(connectionString);
                    try
                    {
                        TempDataAdapter = new OracleDataAdapter(mySQL, myConnection);
                        TempDataSet = new DataSet();
                        TempDataTable = new DataTable();
                        TempDataAdapter.Fill(TempDataSet);
                        TempDataTable = TempDataSet.Tables[0].Copy();
                        /* If the main dataset is empty, create a table by cloning from temp dataset, otherwise
                         copy all rows to existing table.*/
                        if (MainDataSet.Tables.Count == 0)
                        {
                            MainDataSet.Tables.Add(TempDataTable);
                            MainDataTable = MainDataSet.Tables[0];
                        }
                        else
                        {
                            foreach (DataRow dr in TempDataTable.Rows)
                            {
                                MainDataTable.ImportRow(dr);
                            }
                        }
                    }
                    catch (OracleException e)
                    {
                        Label1.Visible = true;
                        Label1.Text = Label1.Text + e.Message + " on " + li.Text + "<br>";
    
                    }
                    finally
                    {
                        if (myConnection != null)
                        {
                            myConnection.Close();
                            myConnection = null;
                        }
                        TempDataSet = null;
                        TempDataAdapter = null;
                        TempDataTable = null;
    
                    }
                }
            }
            GridView1.DataSourceID = String.Empty;
            if (MainDataSet.Tables.Count != 0)
            {
            GridView1.DataSource = MainDataSet;
                if (GridView1.DataSource != null)
                {
                    GridView1.DataBind();
                }
            }
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            BindData(TextBox1.Text);
        }
    

    谢谢

    更新:SQL代码各不相同,对于测试,我使用了非常简单的查询,例如 select sysdate from dual select name from v$database BindData(TextBox1.Text)

    更新:从ASP.NET代码连接到多个数据库,而不是一个或所有数据库上的存储过程,或者复制到一个数据库,原因有两个。首先,所讨论的dbs是几个类似生产环境的频繁更新副本(通常是每个客户机的开发、测试和支持),因此对实际dbs所做的任何事情都必须定期更新或重做,因为它们无论如何都要重新加载。第二,我事先不知道会运行什么样的查询,这个表单让我只需键入例如。 select count (name) from dbusers 针对十几个数据库,无需首先考虑将dbusers表复制到主数据库。

    5 回复  |  直到 16 年前
        1
  •  3
  •   Rune Grimstad    16 年前

    如果在DataTable对象上运行DataAdapter.Fill方法,该表将使用查询结果进行更新。因此,不必创建新的DataTable和DataSet对象,然后手动复制DataRows,您只需将行添加到同一个表中即可。

    试试这样(在未经测试的C代码中):

    public void BindData(string mySQL)
    {
      OracleConnection myConnection;
      // Empty connection string for now
      OracleDataAdapter MainDataAdapter = new OracleDataAdapter(mySQL, ""); 
      DataTable MainDataTable = new DataTable();
      string connectionString = "";
      Label1.Visible = false;
      Label1.Text = "";
    
      foreach (ListItem li in CheckBoxList1.Items)
      {
        if (li.Selected)
        {
          connectionString = "Data Source=" + li.Text + "";
          connectionString += ";Persist Security Info=True;User ID=user;Password=pass;Unicode=True";
          MainDataAdapter.SelectCommand.Connection.ConnectionString = connectionString
          try
          {
            MainDataAdapter.Fill(MainDataTable);
          }
          catch (OracleException e)
          {
            Label1.Visible = true;
            Label1.Text = Label1.Text + e.Message + " on " + li.Text + "<br>";
          }
        }
      }
      GridView1.DataSourceID = String.Empty;
      GridView1.DataSource = MainDataTable;
      GridView1.DataBind();
    }
    

    我做了以下更改:

    • 创建了一个数据适配器,并使用mySQL查询为其分配了一个select命令
    • 为连接提供了一个空连接字符串
    • 将您的循环更改为仅设置SelectCommand的连接字符串(您可能需要将此更改为使用新的SelectCommand替换SelectCommand)
    • 已删除连接。Close()调用。DataAdapter会自动执行此操作。

    就这样。如果您的数据库处于脱机状态,您仍然会遇到速度变慢的问题,但至少代码更简单、更快,因为您不必复制表之间的所有行。

    还有一件事。您可能可以在连接字符串中为连接设置超时。试着降低这个。

        2
  •  2
  •   Nathan Prather    16 年前

    可能有很多因素导致速度变慢。正在执行的sql语句中有哪些运行缓慢?

    如果有人读到这篇文章是在使用sql server,Scott Mitchell刚刚写了一篇很好的文章来帮助解决sql server中的问题: Running the Same Query Against Multiple Databases

        3
  •  1
  •   Jaime Febres    16 年前

    为什么不使用复制来实现这一点呢……您知道,一个中央数据库正在汇集来自其他数据库的新数据,只需对这组数据执行查询,这组数据是 从不 就要倒下了。

        4
  •  1
  •   FlySwat    16 年前

    为什么不在一个oracle数据库上运行一个存储过程,并让存储过程调用其他数据库?这是处理链接数据库的正确方法。

        5
  •  0
  •   Community CDub    8 年前

    听起来你可能对这个更一般的问题更感兴趣: 如何在不挂起UI的情况下执行长时间运行的任务 (ASP或WinForms)?

    这个问题的答案是使用多个 Threads . 我将在一个单独的线程上执行这样一个长时间运行的任务,并向用户显示一个包含当前结果的页面(自动刷新或使用ajax等)。您甚至可以为每个可用的处理器创建任务,以最大限度地利用您的机器(使用类似 Parallel Extensions ); 然而,这大大增加了复杂性,而且很难做到正确。

    here (由唯一的 Jon Skeet )