如何用多个表填充数据集?

Posted

技术标签:

【中文标题】如何用多个表填充数据集?【英文标题】: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。 ***.com/a/334667/284240 reader 的唯一优势是您可以一次将一条记录流式传输,而不是将所有记录加载到内存中。 【参考方案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;

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。

以上是关于如何用多个表填充数据集?的主要内容,如果未能解决你的问题,请参考以下文章

如何用一个数据集更新两个表?

使用存储过程中的表名填充数据集

如何用FastReport制作动态报表

如何用平均值填充空值

如何用小数据集训练神经网络或如何在没有人工干预的情况下制作大数据集?

如何用Matlab 画出鸢尾花数据集的这个图?求Matlab代码,谢谢。