1

SPを呼び出すクエリを実行すると、そのSPはデータを返します...しかし、DataAdapterを使用して呼び出すと、結果データが得られません。代わりにDataReaderを使用すると、データが得られます。データベースはSQLServerであり、変更できない理由でコードはOleDbを使用しています。

これらの2つの呼び出しは、異なるものを返します。

    String commandText = "Declare @return_value int;  exec dbo.copyTemplate ? , ? , ? , ? , ? ,  ? ,   ?, Null , 0 , @return_value;";

    Console.WriteLine("Data Adapter");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbDataAdapter da = new OleDbDataAdapter(commandText, con))
        using (DataTable table = new DataTable("table"))
        {
            da.SelectCommand.Parameters.AddWithValue("?",9).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", "AAAAB").DbType = DbType.String;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            da.SelectCommand.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            da.Fill(table);

            foreach (DataRow dr in table.Rows)
            {
                foreach (DataColumn dc in table.Columns)
                {
                    Console.Write(dr[dc].ToString());
                    Console.Write(" ");
                }
                Console.WriteLine();
            }
        }
    }
    Console.WriteLine("Data Reader");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbCommand cmd = new OleDbCommand(commandText, con))
        {
            cmd.Parameters.AddWithValue("?", 9).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", "AAAAC").DbType = DbType.String;
            cmd.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            cmd.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            con.Open();

            using (OleDbDataReader reader = cmd.ExecuteReader())
                while (reader.Read())
                {
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        Console.Write(reader.GetValue(i) ?? "null");
                        Console.Write(" ");
                    }
                    Console.WriteLine();
                }
        }
    }

    Console.ReadKey(true);

このコードは次を返します:

Data Adapter
Data Reader
1057

このコードは何百回も呼び出すことができ、DataReaderでは常にDataAdapterで何も取得しません。また、2番目のパラメーターには何でも含めることができ、SPの結果は何も変更されません。2つの呼び出し間でパラメーター値を交換したり、順序を変更したりできます...結果は同じです:(

なぜこれが起こっているのか分かりません。

何が問題になるのか、誰か考えがありますか?

乾杯。

更新:DataTableの代わりにDataSetに入力すると、次の結果が得られます。

    Console.WriteLine("Data Adapter with DataSet");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbDataAdapter da = new OleDbDataAdapter(commandText, con))
        using (DataSet ds = new DataSet("table"))
        {
            da.SelectCommand.Parameters.AddWithValue("?",9).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", "AAAAB").DbType = DbType.String;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            da.SelectCommand.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            da.Fill(ds);

            foreach (DataTable table in ds.Tables)
                foreach (DataRow dr in table.Rows)
                {
                    foreach (DataColumn dc in table.Columns)
                    {
                        Console.Write(dr[dc].ToString());
                        Console.Write(" ");
                    }
                    Console.WriteLine();
                }
        }
    }

ただし、DataSetにはテーブルが1つしかないため、DataAdapter.Fill(DataTable)が機能しない理由がわかりません。

4

1 に答える 1

2

問題は、ストアドプロシージャが(@leppieが指摘したように)いくつかの結果セットを返し、最初のセットは空で、2番目のプロシージャには実際の結果が含まれていることです。

DataAdapter.Fill(DataTable)は、最初の結果セットのみを取得してDataTableに配置します。その結果は空であるため、空のDataTableを取得します。DataTableはすでに作成されているため、「null」を取得することはできません。アダプターはDataTableを埋めるだけです。

DataReaderはすべての結果セットを調べます。そのため、ここで結果を取得しましたが、そのように使用するのは間違っています。最初の結果セットはnullであるため、現時点では問題はありませんが、ストアドプロシージャまたはアドホッククエリが複数の結果セットを返す場合、異なる列が設定され、1つのDataTableですべてを台無しにする2つ以上の異なるテーブルを取得できます。

DataAdapter.Fill(DataSet)は、結果セットごとにDataTableを取得します。最初のデータはnullであり、2番目のデータはデータのみであるため、DataTableが1つだけのDataSetを取得します。

これを解決するための正しくて簡単な方法は、ストアドプロシージャを修正し、結果セットを1つだけ返すことです。おそらく、SPに空の変数などを返すものがあります。複数の結果セットをサポートする場合は、DataAdapter.Fill(DataSet)を使用し、入力されたDataSetに複数のDataTableが存在する可能性があるという考えに対処する必要があります。

http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/8fdbaa2d-1f1e-461f-8505-b80ea0c415f2

于 2010-10-14T14:51:37.423 に答える