SQLサーバーテーブルのスキーマを使用して空のDataTableオブジェクトを作成するための最良の方法は何ですか?
言及する価値があると思うステートメントは SET FMTONLY :
SET FMTONLY ON;
SELECT * FROM SomeTable
SET FMTONLY OFF;
SET FMTONLYがオンになっているときの要求のため、行は処理されず、クライアントに送信されません。
これが便利な理由は、任意のクエリ/ストアドプロシージャを指定して、結果セットのメタデータのみを返すことができるためです。
これらのソリューションはすべて正しいですが、このシナリオで合理化された純粋なコードソリューションが必要な場合。
CommandBehavior.SchemaOnlyがExecuteReader関数で指定されているため、このソリューションではデータは返されません( コマンド動作ドキュメント )
CommandBehavior.SchemaOnlyソリューションは、SET FMTONLYONを追加します。クエリが実行される前の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;
}
試してください:SELECT TOP 0 * FROM [TableName]
sQLDataAdapterを使用してDataSetに入力し、そのDataSetからテーブルを取得します。
これを実行したい時点でコピーしたいテーブルを含むSQLデータベースに接続できると仮定すると、従来の結果セットからデータテーブルへの変換を使用できます。
select * from <tablename> where 1=2
ソースクエリとして。
これにより、ソーステーブルの構造を含む空の結果セットが返されます。
これが私がしたことです:
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
これは機能します:
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
これは古い質問であり、SQLServerに固有のものであることを私は知っています。ただし、さまざまなデータベースで機能する汎用ソリューションを探している場合は、Richardのソリューションを使用しますが、"SELECT * FROM {0} WHERE 1=0"
を使用するように変更し、汎用ADO.NetタイプIDataReader、IDbCommandなどを使用するようにタイプを変更します。
最新のリレーショナルデータベースのほとんどは、1 = 0の条件を識別するのに十分インテリジェントであり、通常のテーブルスキャンクエリのように実行されません。私はこれをSQLServerで試しましたが、OracleとDB2のテーブルには1億件のレコードもあります。すべてが数ミリ秒で空の結果を返します。
これが私がしたことで、すぐに使える空の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 ();