web-dev-qa-db-ja.com

DataReaderから返された単一の行のみを適用します

私はこれを私のコードでかなりたくさん書いているようです:

using (var reader = cmd.ExecuteReader())
{
    if (reader.Read())
    {
        result = new User((int)reader["UserId"], reader["UserName"].ToString());
    }

    if (reader.Read())
    {
        throw new DataException("multiple rows returned from query");
    }
}

私が知らない、これを行うための組み込みの方法はありますか?

15

わかりませんが、このコードは拡張メソッドに委任できます。

public static R Single<R>(this DataReader reader, Func<DataReader,R> selector) {
    R result = default(R);
    if (reader.Read())
        result = selector(reader);
    if (reader.Read())
        throw new DataException("multiple rows returned from query");
    return result;
}

そのように使用される:

using (var reader = cmd.ExecuteReader())
{
    User u = reader.Single(r => new User((int)r["UserId"], r["UserName"].ToString()))
}

コードの重複からあなたを救います。

16
flq

これは、目標が何であるかによって、役立つ場合と役に立たない場合があります。適切な例外をスローするために複数の行が返されたことを検出する必要がある場合、これは役に立ちません。

結果が1つだけ返されるようにしたい場合は、このメソッドを使用するとパフォーマンスが向上する可能性があります。私の理解では、データプロバイダーはこれを使用して、単一行の結果を見越してクエリを最適化できます。

いずれの場合も、SqlCommand.ExecuteReaderを使用してデータリーダーを作成しますが、CommandBehavior列挙体(具体的にはCommandBehavior.SingleRow)から引数を渡します。 ExecuteReaderは、これを受け入れるためにオーバーロードされています。

CommandBehavior列挙型

SqlCommand.ExecuteReaderオーバーロード

したがって、コードは次のようになります。

using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
    if (reader.Read())
    {
        result = new User((int)reader["UserId"], reader["UserName"].ToString());
    }
}
11
bubbleking

SQLを使用してデータをフェッチしている場合、データリーダーを使用する必要があるすべてのインスタンスでその種のコーディングを削除できるようにすることで役立つ場合があります。

SELECT TOP ([Number of rows you want to be selected]) 
FROM [Table Name] 
WHERE [Condition]

例:

SELECT TOP (1)
FROM tblUsers
WHERE Username = 'Allan Chua'

別のヒントでは、ストアドプロシージャを使用します。これらを使用すると、SQLクエリの繰り返しと不要なコーディングを最小限に抑えることができます。

1
Allan Chua