Принудительно использовать только одну строку, возвращенную из DataReader - PullRequest
14 голосов
/ 20 октября 2011

Я, кажется, довольно много пишу в своем коде:

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

Есть ли какие-то встроенные способы сделать это, о которых я не знаю?

Ответы [ 3 ]

15 голосов
/ 20 октября 2011

Не знаю, но этот код можно делегировать в метод расширения:

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

Спасая вас от дублирования кода.

10 голосов
/ 29 января 2014

Это может или не может помочь в зависимости от вашей цели. Если вам нужно определить, что было возвращено несколько строк, чтобы вызвать соответствующее исключение, это не поможет.

Если вы просто хотите убедиться, что возвращается только один результат, вы можете получить прирост производительности с помощью этого метода. Насколько я понимаю, поставщики данных могут использовать это для оптимизации запроса в ожидании результата из одной строки.

В любом случае вам нужно использовать SqlCommand.ExecuteReader для создания устройства чтения данных, но передать аргумент из перечисления CommandBehavior (в частности CommandBehavior.SingleRow). ExecuteReader перегружен, чтобы принять это.

Перечисление команд поведения

SqlCommand.ExecuteReader перегрузка

Итак, ваш код может выглядеть так:

using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
    if (reader.Read())
    {
        result = new User((int)reader["UserId"], reader["UserName"].ToString());
    }
}
1 голос
/ 20 октября 2011

Если вы используете sql для извлечения ваших данных, это может помочь, если вы удалите код такого типа в каждом случае, когда вам нужно использовать устройство чтения данных.

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

EX:

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

Еще один совет - используйте хранимые процедуры, их использование может свести к минимуму повторение запросов SQL и ненужное кодирование.

...