【问题标题】:Need to get empty datatable in .net with database table schema需要在.net中使用数据库表模式获取空数据表
【发布时间】:2011-01-20 13:06:53
【问题描述】:

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

【问题讨论】:

    标签: c# .net sql-server ado.net datatable


    【解决方案1】:

    假设您可以连接到包含您想要复制的表的 SQL 数据库,此时您可以使用传统的结果集到数据表转换,使用

    select * from <tablename> where 1=2
    

    作为您的源查询。

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

    【讨论】:

      【解决方案2】:

      尝试: SELECT TOP 0 * FROM [TableName]

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

      【讨论】:

        【解决方案3】:

        我认为值得一提的是SET FMTONLY

        SET FMTONLY ON;
        SELECT * FROM SomeTable
        SET FMTONLY OFF;
        

        当 SET FMTONLY 开启时,由于请求,没有任何行被处理或发送到客户端。

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

        【讨论】:

          【解决方案4】:

          您可以随时创建自己的:

                  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)));
          

          明显的缺点是,每当数据库架构发生变化时,您都必须更新代码。

          【讨论】:

            【解决方案5】:

            这就是我所做的:

            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。

            【讨论】:

              【解决方案6】:

              这行得通:

              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
              

              【讨论】:

                【解决方案7】:
                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
                

                【讨论】:

                  【解决方案8】:

                  所有这些解决方案都是正确的,但是如果您想要一个针对这种情况进行简化的纯代码解决方案。

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

                  CommandBehavior.SchemaOnly 解决方案将添加 SET FMTONLY ON;为您执行查询之前的 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;
                  }
                  

                  【讨论】:

                    【解决方案9】:

                    我知道这是一个老问题,特定于 SQL Server。但是,如果您正在寻找适用于不同数据库的通用解决方案,请使用 Richard 的解决方案,但将其修改为使用 "SELECT * FROM {0} WHERE 1=0" 并将类型更改为使用通用 ADO.Net 类型 IDataReader、IDbCommand 等。

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

                    【讨论】:

                      【解决方案10】:

                      这是我所做的,它提供了一个可以使用的空白 DataTable:

                      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 ();
                      

                      【讨论】:

                        猜你喜欢
                        • 2016-05-09
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-04-20
                        • 1970-01-01
                        • 2014-05-16
                        • 1970-01-01
                        • 1970-01-01
                        • 2022-08-15
                        相关资源
                        最近更新 更多