如何动态生成DataTables以及动态生成Columns和Rows?

时间:2013-04-30 17:41:05

标签: c# datatable

假设我有一个包含2个表的数据库,其中包含以下名称(tbl1tbl2)。 上表中的每一个都有不同的列数,tbl1有3列,而tbl2有4列。

我需要在DataTable中复制上述每个表格。

当然,我可以像下面的代码一样手动完成:

    class 
    {  
      public Main()  
      {
        // for tbl1 with 3 columns.
        string sql = "select * from tbl1"
        MySqlCommand com = new MySqlCommand(sql, con);
        MySqlDataReader dr = com.ExecuteDataReader();
        DataTable dt = GetDataTable(3);

        while (dr.Read())
        {
          if (dr.HasRows)
          {
            dt.Rows.Add(dr[0], dr[1], dr[2]);  <---- Point of interest
          }
        }

        // for tbl2 with 4 columns.
        string sql = "select * from tbl2";
        MySqlCommand com = new MySqlCommand(sql, con);
        MySqlDataReader dr = com.ExecuteDataReader();
        DataTable dt = GetDataTable(4);

        while (dr.Read())
        {
          if (dr.HasRows)
            {
              dt.Rows.Add(dr[0], dr[1], dr[2], dr[3]);  <---- Point of interest
            }
        }
    }

      public DataTable GetDataTable(int columnCount)
      {
        DataTable dt = new DataTable();

        if (columnCount > 0)
        {
          for (int i = 0; i < length; i++)
          {
            dt.Columns.Add(i.ToString(), typeof(object));
          }
        }
        return dt;
      }
    }  

但我想做的是以自动方式完成上述过程,特别是在我指示箭头的部分。

有没有办法像我在列上那样动态添加行?

我想我可以通过使用一个函数来动态添加行,该函数生成将行添加为字符串并将该字符串作为命令调用的过程,但我真的很丢失,不知道该怎么做...请参阅下面的代码。

EX:    
String generated from a function base on number of columns:
    "dt.Rows.Add(dr[0], dr[1], dr[2], dr[3])"
Then, use the string as a command to add rows...

2 个答案:

答案 0 :(得分:4)

使用datareader的GetSchemaTable方法查找您拥有的列数。

像这样的东西(非测试代码,例如):

public DataTable ReadTable(string sql, params object[] parameters) {


    using (var cmd = CreateCommand(sql, parameters))
        {
            var reader = cmd.ExecuteReader();
            if (reader == null)
            {
                return null;
            }

            var schemaTable = reader.GetSchemaTable();
                            DataTable dt = GetTable(schemaTable);

            while (reader.Read())
            {
                var values = new object[reader.FieldCount];
                reader.GetValues(values);
                                    dt.Rows.Add(values);

            }
        }
}

private DataTable GetTable(DataTable schemaTable) {
        if (schemaTable == null || schemaTable.Rows.Count == 0)
        {
            return null;
        }

        var dt = new DataTable();
        foreach (DataRow schemaRow in schemaTable.Rows)
        {
            var col = new DataColumn
            {
                ColumnName = schemaRow["ColumnName"].ToString(),
                                    DataType = schemaRow["DataType"]
                                  // use the debugger to find out the name of the type column in the schematable, 
                                  // and any other properties you need
            };
                            dt.Columns.Add(col);
        }
        return dt;

}

注意:我使用这样的代码不是为了创建DataTable,而是将读取的行转换为IEnumerable对象(我们使用的是一些不使用sql语句自动执行此操作的DB2实体框架库)。

正如许多人提到的,如果您只想阅读DataTable,请创建一个DataAdapter并使用Fill()方法。

// Assumes that connection is a valid SqlConnection object.
string queryString = 
 "SELECT CustomerID, CompanyName FROM dbo.Customers";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);

DataSet customers = new DataSet();
adapter.Fill(customers, "Customers");

http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.80).aspx

答案 1 :(得分:1)

这是一个填充数据集以获取结果的VB示例(从我的一个包装器修改)。

根本没有行(数据适配器为您完成)

Sub ExampleUsage()
    Dim ds as new dataset
    ExecuteDataSetFill(AnSqlConnection, "SELECT * FROM Something; SELECT * from SomethingElse", ds)
    Dim Tbl1 as datatable=ds.Tables(0)
    Dim Tbl2 as datatable=ds.Tables(1)
    ' both tables will ALREADY HAVE all the rows in them, there is no reader involved.
End Sub
    ''' <summary>
    ''' Performs a FILL operation on an adapter, populating the passed in dataset for the current "OpenConnection", returns the return value of the FILL command.
    ''' </summary>
    ''' <param name="sSQL">SQL to use for the command to issue</param>
    ''' <param name="dsToFill">a DataSet to FILL</param>
    ''' <returns>The Return Value of the FILL operation</returns>
    Public Overridable Function ExecuteDataSetFill(ByVal con As SqlClient.SqlConnection, ByVal sSQL As String, ByVal dsToFill As DataSet) As Integer
        Dim da As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter
        Dim com As SqlClient.SqlCommand = con.CreateCommand
        com.CommandText = sSQL
        da.SelectCommand = com
        Dim iOut As Integer
        dsToFill.EnforceConstraints = False
        Dim sw As Stopwatch = Stopwatch.StartNew
        Try
            iOut = da.Fill(dsToFill)
        Catch ex As Exception
            Throw New Exception("DataSet Error. " & vbCrLf & "SQL = " & sSQL & vbCrLf & "Error=" & ex.ToString, ex)
        End Try
        sw.Stop()
        Return iOut
    End Function