C# 需要使用数据库表架构获取.net中的空datatable

C# 需要使用数据库表架构获取.net中的空datatable,c#,.net,sql-server,ado.net,datatable,C#,.net,Sql Server,Ado.net,Datatable,使用sql server表的架构创建空DataTable对象的最佳方法是什么?假设您可以在执行此操作时连接到包含要复制的表的sql数据库,您可以使用常规的resultset到DataTable转换,使用 select * from <tablename> where 1=2 选择*其中1=2 作为源查询 这将返回一个带有源表结构的空结果集。请尝试: 从[TableName]中选择顶部0* 然后使用SQLDataAdapter填充数据集,然后从该数据集获取表。我认为值得一提的一句话

使用sql server表的架构创建空DataTable对象的最佳方法是什么?

假设您可以在执行此操作时连接到包含要复制的表的sql数据库,您可以使用常规的resultset到DataTable转换,使用

select * from <tablename> where 1=2
选择*其中1=2
作为源查询

这将返回一个带有源表结构的空结果集。

请尝试:
从[TableName]中选择顶部0*


然后使用SQLDataAdapter填充数据集,然后从该数据集获取表。

我认为值得一提的一句话是:

当SET FMTONLY处于启用状态时,由于请求的原因,不会处理行或将行发送到客户端


这之所以方便,是因为您可以提供任何查询/存储过程,并仅返回结果集的元数据。

您始终可以创建自己的:

        DataTable table = new DataTable("TableName");

        table.Columns.Add(new DataColumn("Col1", typeof(int)));
        table.Columns.Add(new DataColumn("Col2", typeof(int)));
        table.Columns.Add(new DataColumn("Col3", typeof(string)));
        table.Columns.Add(new DataColumn("Col4", typeof(int)));
        table.Columns.Add(new DataColumn("Col5", typeof(string)));
一个明显的缺点是,每当数据库架构发生更改时,您都必须更新代码。

以下是我所做的:

var conn = new SqlConnection("someConnString");
var cmd = new SqlCommand("SET FMTONLY ON; SELECT * FROM MyTable; SET FMTONLY OFF;",conn); 
var dt = new DataTable();
conn.Open();
dt.Load(cmd.ExecuteReader());
conn.Dispose();
效果很好。谢谢AdaTheDev。

这项工作:

Class BlankTableWithSourceTableSchema
    Inherits DataTable
    Public Sub New(ByVal connstr As String, ByVal sourcetable As String)
        Try
            Using connection As SqlServerCe.SqlCeConnection = New SqlServerCe.SqlCeConnection(connstr)
                Dim adapter As SqlServerCe.SqlCeDataAdapter = New SqlServerCe.SqlCeDataAdapter("SELECT * FROM " & sourcetable, connection)
                adapter.TableMappings.Add("Table", "ABlankTable")
                adapter.FillSchema(Me, SchemaType.Mapped)
            End Using
        Catch ex As Exception
        End Try
    End Sub
End Class

所有这些解决方案都是正确的,但是如果您想要一个针对这个场景进行优化的纯代码解决方案

由于在ExecuteReader函数()上指定了CommandBehavior.SchemaOnly,因此此解决方案中未返回任何数据

CommandBehavior.SchemaOnly解决方案将快速添加集合;在为您执行查询之前使用sql,这样可以保持代码的整洁

public static DataTable GetDataTableSchemaFromTable(string tableName, SqlConnection sqlConn, SqlTransaction transaction)
{
    DataTable dtResult = new DataTable();

    using (SqlCommand command = sqlConn.CreateCommand())
    {
        command.CommandText = String.Format("SELECT TOP 1 * FROM {0}", tableName);
        command.CommandType = CommandType.Text;
        if (transaction != null)
        {
            command.Transaction = transaction;
        }

        SqlDataReader reader = command.ExecuteReader(CommandBehavior.SchemaOnly);

        dtResult.Load(reader);

    }

    return dtResult;
}

我知道这是一个老问题,专门针对SQL Server。但是,如果您正在寻找能够跨不同数据库工作的通用解决方案,请使用Richard的解决方案,但将其修改为使用
“从{0}中选择*其中1=0”
,并将类型更改为使用通用ADO.Net类型IDataReader、IDbCommand等


大多数现代关系数据库都足够智能,能够识别1=0条件,并且不会像常规的tablescan查询那样运行它。我在SQL Server、Oracle和DB2上尝试过这一点,其中表也只有1亿条记录。All确实会在几毫秒内返回空结果。

以下是我所做的,它提供了一个空白数据表,可以随时使用:

SqlConnection _sqlConnection = new SqlConnection ();
_sqlConnection.ConnectionString = @"Data Source=<SQL_Server/Instance>; Initial Catalog=<database_name>; Integrated Security=False; User ID=<user_id>;Password=<passowrd>";
_sqlConnection.Open ();
SqlCommand _sqlCommand = new SqlCommand ( "select * from DatabaseName.dbo.viewName", _sqlConnection ); 
_dataSet = new DataSet ();
_sqlDataAdapter = new SqlDataAdapter ( _sqlCommand );
_sqlDataAdapter.Fill ( _dataSet );
_schemaTable = new DataTable ();
_sqlDataAdapter.FillSchema ( _schemaTable, SchemaType.Source );
dataGridView.DataSource = _schemaTable;
_sqlConnection.Close ();
SqlConnection\u SqlConnection=newsqlconnection();
_sqlConnection.ConnectionString=@“数据源=;初始目录=;集成安全性=False;用户ID=;密码=”;
_Open();
SqlCommand _SqlCommand=newsqlcommand(“从DatabaseName.dbo.viewName中选择*,_sqlConnection”);
_数据集=新数据集();
_sqlDataAdapter=新的sqlDataAdapter(_sqlCommand);
_sqlDataAdapter.Fill(_数据集);
_schemaTable=newdatatable();
_sqlDataAdapter.FillSchema(_schemaTable,SchemaType.Source);
dataGridView.DataSource=\u schemaTable;
_sqlConnection.Close();
public static DataTable GetDataTableSchemaFromTable(string tableName, SqlConnection sqlConn, SqlTransaction transaction)
{
    DataTable dtResult = new DataTable();

    using (SqlCommand command = sqlConn.CreateCommand())
    {
        command.CommandText = String.Format("SELECT TOP 1 * FROM {0}", tableName);
        command.CommandType = CommandType.Text;
        if (transaction != null)
        {
            command.Transaction = transaction;
        }

        SqlDataReader reader = command.ExecuteReader(CommandBehavior.SchemaOnly);

        dtResult.Load(reader);

    }

    return dtResult;
}
SqlConnection _sqlConnection = new SqlConnection ();
_sqlConnection.ConnectionString = @"Data Source=<SQL_Server/Instance>; Initial Catalog=<database_name>; Integrated Security=False; User ID=<user_id>;Password=<passowrd>";
_sqlConnection.Open ();
SqlCommand _sqlCommand = new SqlCommand ( "select * from DatabaseName.dbo.viewName", _sqlConnection ); 
_dataSet = new DataSet ();
_sqlDataAdapter = new SqlDataAdapter ( _sqlCommand );
_sqlDataAdapter.Fill ( _dataSet );
_schemaTable = new DataTable ();
_sqlDataAdapter.FillSchema ( _schemaTable, SchemaType.Source );
dataGridView.DataSource = _schemaTable;
_sqlConnection.Close ();