仅强制从DataReader返回单行

时间:2011-10-20 13:18:27

标签: c# .net ado.net sqldatareader 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");
    }
}

有一些内置的方法可以做到这一点我不知道吗?

3 个答案:

答案 0 :(得分: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()))
}

免于代码重复。

答案 1 :(得分:10)

根据您的目标,这可能会有所帮助,也可能不会有所帮助。如果您需要检测返回多行以便抛出适当的异常,那么这将无济于事。

如果您只想确保只返回一个结果,则可以使用此方法获得性能提升。据我所知,数据提供者可以使用它来优化查询,以预测单行结果。

在任何情况下,您要做的是使用SqlCommand.ExecuteReader创建数据读取器,但从CommandBehavior枚举(特别是CommandBehavior.SingleRow)传入参数。重载ExecuteReader以接受此操作。

CommandBehavior enum

SqlCommand.ExecuteReader overload

所以你的代码可能如下所示:

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

答案 2 :(得分:1)

如果您使用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查询的重复和不必要的编码。