6

SqlDataReaderを返すメソッド(「GetDataReader」と呼びましょう)があります。これは、データベースへの永続的な接続を維持するSingletonDataFactoryクラス内にあります。

これに伴う問題は、返された後も、DataReaderがDataFactoryのConnectionオブジェクトに「接続」されていることです。したがって、GetDataReaderを呼び出すコードが、戻ってくるDataReaderでClose()を呼び出すことを確認する必要があります。そうしないと、次のように接続が「ロック」されます。

このコマンドに関連付けられている開いているDataReaderがすでにあり、最初に閉じる必要があります。

GetDataReaderから返送する前に、DataReaderを「デタッチ」するにはどうすればよいですか?それか、クローンを作成してクローンを送り返しますか?呼び出し元のコードを常に明示的に閉じる必要はありません。

ここにはベストプラクティスが必要です。

アップデート:

ご意見ありがとうございます。肝心なのは、DataReaderを使用する習慣を失い、DataTablesに切り替える必要があるということです。それらははるかに管理しやすいです。

また、接続プールに関する注意事項にも感謝します。私はそれについて知っていましたが、2つと2つを組み合わせなかっただけで、車輪の再発明をしていることに気づきました。

4

5 に答える 5

7

DataReaderは、不要になるまでデータベースに接続されたままである必要があります。これは、DataReaderを使用する性質であるため、DataReader自体を「切断」することはできません。データリーダーを使い終わったら、データリーダーを閉じる必要があります(.Close())。そうすると、それ以上使用できなくなります。

.NET 2.0以降、SQL 2005以降を使用している場合は、ここで説明するようにMARS(複数のアクティブな結果セット)を使用できます。これにより、複数のデータリーダーに単一の接続を使用でき、接続文字列を変更するだけで済みます。ただし、SqlDataReadersは、コードを希望どおりに渡すには理想的ではありません。

または(これが必要だと思います)、DataSet / DataTablesが入ってくる切断された結果セットを使用することもできます。SqlDataAdapterを使用して、クエリのすべての結果をDataSet/DataTableに入力します。その後、接続を他の目的に使用したり、接続を閉じたりすることができます。これは、メモリ内の結果セットには影響しません。開いているデータベース接続を維持しなくても、結果セットをコードに渡すことができます。

于 2010-01-18T15:31:25.303 に答える
2

データベース接続を永続化しないでください。「接続プール」と呼ばれる機能があります。新しい接続を取得するのは費用がかかりません。

于 2010-01-18T15:30:11.823 に答える
1

一般に、ベストプラクティスは、複数のユーザーによる同時アクセスを許可するために、永続的な接続ではなく接続プールを使用することです。あなたがやりたいことをするために私が考えることができる唯一の方法は、リーダーからDataSetをロードし、それを返すことです。

于 2010-01-18T15:30:39.550 に答える
1

データセット(切断された埋め込みデータ)とデータリーダー(データなし)が混同されている可能性があると思います。SqlCnnectionのないDataReaderは...うーん...ただのリーダー、つまりデータなし;-)

あなたの問題はあなたの考え方のさらに上にあると思います。あなたはすべてを手作業で行うことに慣れている古い学校のプログラマーだと思います。ドットネットの「管理された」世界では、多くのものが管理されます。ADO.NETにはすでに効果的なデータ接続プールシステムがあり、独自のプールを維持する必要はありません。

-オシーン

于 2010-01-18T15:30:47.020 に答える
0

これは、接続に対してSQLを実行し、サーバーから切断するための便利なヘルパーメソッドです。

public static DbDataReader ExecuteReaderClient(DbConnection connection, DbTransaction transaction, String commandText)
{
    DbCommand command = connection.CreateCommand();
    command.CommandText = commandText;
    if (transaction != null)
        command.Transaction = transaction;

    DbDataAdapter adapter = DbProviderFactories.GetFactory(connection).CreateDataAdapter();

    adapter.SelectCommand = command;
    DataSet dataset = new DataSet();

    try
    {
        adapter.Fill(dataset);
    }
    catch (Exception e)
    {
        throw new Exception(
                  e.Message + "\r\n" +
                  "Command Text" + "\r\n" +
                  commandText, e);
    }

    try
    {
        return dataset.CreateDataReader();
    }
    finally
    {
        dataset.Dispose();
    }
}
于 2017-11-23T18:31:31.143 に答える