【问题标题】:How to fill Dataset with multiple tables?如何用多个表填充数据集?
【发布时间】:2012-07-05 22:36:29
【问题描述】:

我正在尝试填充包含 2 个具有一对多关系的表的 DataSet。 我正在使用 DataReader 来实现这一点:

    public DataSet SelectOne(int id)
    {
        DataSet result = new DataSet();
        using (DbCommand command = Connection.CreateCommand())
        {
            command.CommandText = "select * from table1";

            var param = ParametersBuilder.CreateByKey(command, "ID", id, null);
            command.Parameters.Add(param);

            Connection.Open();
            using (DbDataReader reader = command.ExecuteReader())
            {
                result.MainTable.Load(reader);
            }
            Connection.Close();
        }
        return result;
    }

但是我只有一张桌子坐满了。如何实现我的目标 - 填写两个表格?

如果可能的话,我想使用 DataReader 而不是 DataAdapter。

【问题讨论】:

  • 为什么你会期望两个表都被填满?您的命令仅包含一个返回单个表的 select 语句。
  • 为什么不使用SqlDataAdapter 及其Fill(...) 方法而不是DbCommand
  • @Nikola Anusev - 我知道,所以我只是提出任何建议
  • @jonnyGold - 预演。 DataReader 快,DataAdapter 慢。这对我来说至关重要
  • @AndriyZakharko:DataAdapter 在后台也使用了 DataReader。 stackoverflow.com/a/334667/284240 reader 的唯一优势是您可以一次将一条记录流式传输,而不是将所有记录加载到内存中。

标签: c# sql ado.net dataset datareader


【解决方案1】:

如果您发出带有多个选择语句的单个命令,您可以使用 NextResult 方法移动到数据读取器中的下一个结果集:http://msdn.microsoft.com/en-us/library/system.data.idatareader.nextresult.aspx

我展示了它的外观:

public DataSet SelectOne(int id)
{
    DataSet result = new DataSet();
    using (DbCommand command = Connection.CreateCommand())
    {
        command.CommandText = @"
select * from table1
select * from table2
        ";

        var param = ParametersBuilder.CreateByKey(command, "ID", id, null);
        command.Parameters.Add(param);

        Connection.Open();
        using (DbDataReader reader = command.ExecuteReader())
        {
            result.MainTable.Load(reader);
            reader.NextResult();
            result.SecondTable.Load(reader);
            // ...
        }
        Connection.Close();
    }
    return result;
}

【讨论】:

  • 你可以做result.Load(reader)Load 方法将处理多个结果集。
  • @AMissico,是的,但是不能用 DataSet.Load 明确说明要填充哪个结果集的表,如果您以其他顺序定义表,它将中断。您还必须说明其他参数。
  • 你今天让我笑了。
【解决方案2】:

Here is very good answer of your question

请参阅上面 MSDN 页面上提到的示例:-

【讨论】:

    【解决方案3】:

    可以通过向数据库发送多个请求来填充具有多个表的 DataSet,或者以更快的方式:可以在单个请求中将多个 SELECT 语句发送到数据库服务器。这里的问题是从查询生成的表具有自动名称 Table 和 Table1。但是,生成的表名可以映射到应在 DataSet 中使用的名称。

    SqlDataAdapter adapter = new SqlDataAdapter(
          "SELECT * FROM Customers; SELECT * FROM Orders", connection);
    adapter.TableMappings.Add("Table", "Customer");
    adapter.TableMappings.Add("Table1", "Order");
    
    adapter.Fill(ds);
    

    【讨论】:

    • 感谢您的回复,但根据我的任务 - 我需要使用 DataReader 而不是 DataAdapter :在我的问题中有所描述
    • 用 TableMappings.Add 添加不是必要的
    • @Iman - 如果您按照示例将 SQL 发送到服务器,则可能没有必要,但如果您正在调用存储过程并返回多个 SELECT,则可能没有必要。这个答案对我很有用
    【解决方案4】:

    这是一个老话题,但对某些人来说可能有用:

            DataSet someDataSet = new DataSet();
            SqlDataAdapter adapt = new SqlDataAdapter();
    
            using(SqlConnection connection = new SqlConnection(ConnString))
            {
                connection.Open();
                SqlCommand comm1 = new SqlCommand("SELECT * FROM whateverTable", connection);
                SqlCommand comm2g = new SqlCommand("SELECT * FROM whateverTable WHERE condition = @0", connection);
                commProcessing.Parameters.AddWithValue("@0", "value");
                someDataSet.Tables.Add("Table1");
                someDataSet.Tables.Add("Table2");
    
                adapt.SelectCommand = comm1;
                adapt.Fill(someDataSet.Tables["Table1"]);
                adapt.SelectCommand = comm2;
                adapt.Fill(someDataSet.Tables["Table2"]);
            }
    

    【讨论】:

    • 如果 sql(store proc) 返回多个表,该如何处理?
    • 你可以使用adapt.Fill(someDataSet),而不是adapt.Fill(someDataSet.Tables["Table1"])。因为当然你的存储过程会重新运行表,但前提是它真的返回 TABLES 而不是来自多个表的一组 COLUMNS。
    • 感谢您的回复,会试试这个东西:-)
    【解决方案5】:
    protected void Page_Load(object sender, EventArgs e)
    {
        SqlConnection con = new SqlConnection("data source=.;uid=sa;pwd=123;database=shop");
        //SqlCommand cmd = new SqlCommand("select * from tblemployees", con);
        //SqlCommand cmd1 = new SqlCommand("select * from tblproducts", con);
        //SqlDataAdapter da = new SqlDataAdapter();
    
        //DataSet ds = new DataSet();
        //ds.Tables.Add("emp");
        //ds.Tables.Add("products");
        //da.SelectCommand = cmd;
        //da.Fill(ds.Tables["emp"]);
        //da.SelectCommand = cmd1;
    
        //da.Fill(ds.Tables["products"]);
        SqlDataAdapter da = new SqlDataAdapter("select * from tblemployees", con);
        DataSet ds = new DataSet();
        da.Fill(ds, "em");
        da = new SqlDataAdapter("select * from tblproducts", con);
        da.Fill(ds, "prod");
    
        GridView1.DataSource = ds.Tables["em"];
        GridView1.DataBind();
        GridView2.DataSource = ds.Tables["prod"];
        GridView2.DataBind();
    }
    

    【讨论】:

    • 请添加一些解释。
    【解决方案6】:
             string connetionString = null;
            SqlConnection connection ;
            SqlCommand command ;
            SqlDataAdapter adapter = new SqlDataAdapter();
            DataSet ds = new DataSet();
            int i = 0;
            string firstSql = null;
            string secondSql = null;
    
            connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
            firstSql = "Your First SQL Statement Here";
            secondSql = "Your Second SQL Statement Here";
            connection = new SqlConnection(connetionString);
    
            try
            {
                connection.Open();
    
                command = new SqlCommand(firstSql, connection);
                adapter.SelectCommand = command;
                adapter.Fill(ds, "First Table");
    
                adapter.SelectCommand.CommandText = secondSql;
                adapter.Fill(ds, "Second Table");
    
                adapter.Dispose();
                command.Dispose();
                connection.Close();
    
                //retrieve first table data 
                for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
                {
                    MessageBox.Show(ds.Tables[0].Rows[i].ItemArray[0] + " -- " + ds.Tables[0].Rows[i].ItemArray[1]);
                }
                //retrieve second table data 
                for (i = 0; i <= ds.Tables[1].Rows.Count - 1; i++)
                {
                    MessageBox.Show(ds.Tables[1].Rows[i].ItemArray[0] + " -- " + ds.Tables[1].Rows[i].ItemArray[1]);
    
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can not open connection ! ");
            }
    

    【讨论】:

      【解决方案7】:
      public DataSet GetDataSet()
          {
              try
              {
                  DataSet dsReturn = new DataSet();
                  using (SqlConnection myConnection = new SqlConnection(Core.con))
                  {
                      string query = "select * from table1;  select* from table2";
                      SqlCommand cmd = new SqlCommand(query, myConnection);
                      myConnection.Open();
                      SqlDataReader reader = cmd.ExecuteReader();
                      dsReturn.Load(reader, LoadOption.PreserveChanges, new string[] { "tableOne", "tableTwo" });
                      return dsReturn;
                  }
              }
              catch (Exception)
              {
                  throw;
              }
          }
      

      【讨论】:

        【解决方案8】:

        DataTable 的方法LoadDataReader 上执行NextResult,因此在使用Load 时不应显式调用NextResult,否则将省略序列中的奇数表。

        这是使用DataReader 加载多个表的通用解决方案。

        // your command initialization code here
        // ...
        DataSet ds = new DataSet();
        DataTable t;
        using (DbDataReader reader = command.ExecuteReader())
        {
          while (!reader.IsClosed)
          {
            t = new DataTable();
            t.Load(rs);
            ds.Tables.Add(t);
          }
        }
        

        【讨论】:

        • 这个对我有用,当我不确定在存储过程中返回了多少个单独的表时非常有用(正如我刚刚在使用加密存储过程访问遗留数据库时发现的那样)跨度>
        【解决方案9】:
        DataSet ds = new DataSet();
        using (var reader = cmd.ExecuteReader())
        {
            while (!reader.IsClosed)
                 {
                      ds.Tables.Add().Load(reader);
                 }
        }
        return ds;
        

        【讨论】:

        • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-08
        • 2012-01-03
        • 2013-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多