C# 从SQL Server检索列名称和类型到DataTable C

C# 从SQL Server检索列名称和类型到DataTable C,c#,datatable,ado.net,C#,Datatable,Ado.net,基于SQL server中的现有表构建空数据表的最佳方法是什么?我目前的尝试是这个,它只是手动重新键入,所以它不是很好,特别是对于大型数据集 private DataTable createEmptyReadingDataTableReadyToSaveToDb() { dtbl.Columns.Add("ProductId", typeof(string)); dtbl.Columns.Add("Price", typeof(float)); dtbl.Columns.

基于SQL server中的现有表构建空数据表的最佳方法是什么?我目前的尝试是这个,它只是手动重新键入,所以它不是很好,特别是对于大型数据集

private DataTable createEmptyReadingDataTableReadyToSaveToDb()
{
    dtbl.Columns.Add("ProductId", typeof(string));
    dtbl.Columns.Add("Price", typeof(float));
    dtbl.Columns.Add("Revenue", typeof(float));
    dtbl.Columns.Add("URL", typeof(string));
    //  etc ....
    return dtbl;
}
今天我读了一些关于模式的文章,这对于这个任务来说似乎很自然。这让我比我想象的更困惑。无论如何,下面的这种方法返回一个datatable,返回关于数据集的广泛信息集,但是我没有找到访问器来获取关于下面有趣的datatable的信息。也许我做错了什么

private static DataTable getReadingTableFromSchema()
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
    {
        string sql = "SELECT * FROM [Readings]";
        conn.Open();
        SqlCommand cmd = new SqlCommand(sql, conn);
        SqlDataReader reader = cmd.ExecuteReader();
        DataTable dtbl = reader.GetSchemaTable();
        return dtbl;
    }
}

我也可以尝试DataAdapter读取数据,然后填充数据,基本上是复制DataTable,然后删除所有行以使表为空,但这肯定会影响性能。正确的解决方案是什么?

您可以使用DataAdapter并使用完整架构填充DataTable:

private static DataTable getReadingTableFromSchema()
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
    {
        string sql = "SELECT * FROM [Readings]";
        conn.Open();
        SqlCommand cmd = new SqlCommand(sql, conn);
        DbDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dtbl = new DataTable();
        da.FillSchema(dtbl, SchemaType.Source);
        return dtbl;
    }
}

而且,我建议您也使用using for命令和适配器

您可以使用DataAdapter并用完整架构填充DataTable:

private static DataTable getReadingTableFromSchema()
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
    {
        string sql = "SELECT * FROM [Readings]";
        conn.Open();
        SqlCommand cmd = new SqlCommand(sql, conn);
        DbDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dtbl = new DataTable();
        da.FillSchema(dtbl, SchemaType.Source);
        return dtbl;
    }
}
而且,我建议您也使用using for命令和适配器

使用一点LINQ

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
{
    conn.Open();
    using (var reader = new SqlCommand("SELECT * FROM [Readings] WHERE 1 = 0", conn).ExecuteReader())
    {
        var dataColumns = Enumerable.Range(0, reader.FieldCount)
                                    .Select(i => new DataColumn(reader.GetName(i), reader.GetFieldType(i)))
                                    .ToArray();

        var dataTable = new DataTable("Readings");
        dataTable.Columns.AddRange(dataColumns);
    }
}
使用一点LINQ

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalDbConnnectionString"].ConnectionString))
{
    conn.Open();
    using (var reader = new SqlCommand("SELECT * FROM [Readings] WHERE 1 = 0", conn).ExecuteReader())
    {
        var dataColumns = Enumerable.Range(0, reader.FieldCount)
                                    .Select(i => new DataColumn(reader.GetName(i), reader.GetFieldType(i)))
                                    .ToArray();

        var dataTable = new DataTable("Readings");
        dataTable.Columns.AddRange(dataColumns);
    }
}


你看到我的答案了吗?我看到了。格劳科的回答对我很有效。看起来这项工作最简单。是的,但在我的问题中,我的SQL查询没有带来任何数据,所以它的速度更快,所以如果你要使用Glauco的答案,至少更改SQL查询。最简单的方法是从表中选择*,其中一些值为=到-9999,例如一个keyId字段,或者您可以查找如何使用SchemaType.SourceGood提示,谢谢您Alberto,我对您的答案投了赞成票。有趣的是,您的方法没有加载数据。作为下一步,我需要更深入地了解这一点。你看到我的答案了吗?我看到了。格劳科的回答对我很有效。看起来这项工作最简单。是的,但在我的问题中,我的SQL查询没有带来任何数据,所以它的速度更快,所以如果你要使用Glauco的答案,至少更改SQL查询。最简单的方法是从表中选择*,其中一些值为=到-9999,例如一个keyId字段,或者您可以查找如何使用SchemaType.SourceGood提示,谢谢您Alberto,我对您的答案投了赞成票。有趣的是,您的方法没有加载数据。作为下一步,我需要更深入地了解这一点。DataAdapter没有接收DataTableSure Alberto???的FillSchema重载????你在发言前学习过一点吗基于指定的配置指定的架构。//公共数据表FillSchemaDataTable,SchemaTypeschemaType@GlaucoCucchiar是的,我找到了,在MSDN中你在DataAdapter中找到了任何方法吗?它们接收两个参数DataTable和SchemaType?@GlaucoCucchiar此文档来自SqlDataAdapter,而不是DataAdapter,请看这里@AlbertoMonteiro:嗯,如果创建SqlDataAdapter并将DataAdapter引用为基类,则还具有所有SqlDataAdapter方法。具有此参数的FillSchema是DbDataAdapter方法://Type:System.Data.Common.DbDataAdapter//Assembly:System.Data,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089//程序集位置:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dllDataAdapter没有接收DataTableure Alberto的FillSchema重载????你在发言前学习过一点吗基于指定的配置指定的架构。//公共数据表FillSchemaDataTable,SchemaTypeschemaType@GlaucoCucchiar是的,我找到了,在MSDN中你在DataAdapter中找到了任何方法吗?它们接收两个参数DataTable和SchemaType?@GlaucoCucchiar此文档来自SqlDataAdapter,而不是DataAdapter,请看这里@AlbertoMonteiro:嗯,如果创建SqlDataAdapter并将DataAdapter引用为基类,则还具有所有SqlDataAdapter方法。带有此参数的FillSchema是一个DbDataAdapter方法://Type:System.Data.Common.DbDataAdapter//Assembly:System.Data,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089//Assembly位置:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dlt此解决方案非常复杂且不准确,例如,您没有加载主键…@GlaucoCucchiar为什么复杂?为什么不准确?他要求的是列名和类型,而不是主键。这个解决方案非常复杂和不准确,例如,您不加载主键…@glauccucchiar为什么这么复杂?为什么不准确?他要求的是列名和类型,而不是主键。