C# 仅强制执行从DataReader返回的单行

C# 仅强制执行从DataReader返回的单行,c#,.net,ado.net,sqldatareader,datareader,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

我似乎在我的代码中写了很多:

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

有没有什么我不知道的内在方法

我不知道,但这段代码可以委托给扩展方法:

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

避免代码重复。

如果您使用sql获取数据,这可能有助于您在需要使用数据读取器的每个实例中删除此类代码

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


另一个技巧是使用存储过程,使用存储过程可以最大限度地减少SQL查询的重复和不必要的编码。

这可能有帮助,也可能没有帮助,这取决于您的目标。如果您需要检测返回了多行以抛出适当的异常,那么这将没有帮助

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

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

因此,您的代码可能如下所示:

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

也许如果你能控制查询,你可以在其中做一个
TOP 1
。。。如果你想检查数据库的完整性,也许你应该在你查询的
WHERE
列上放置一个
唯一索引
,而不是这样做。把TOP 1添加到sql查询中怎么样?我不想要TOP 1,我想要一个例外。它们根本不是一回事。为什么这个问题实际上得到了否决票?我们可以通过为
SqlCommand
创建一个扩展方法来避免更多重复的代码<代码>用户u=cmd.Single(…)当然,在这个低级API上,通过一些扩展方法,您可以将它塑造成非常有用的东西:)我不太喜欢
SqlCommand
上的扩展,因为它没有实现任何有用的接口。
SELECT TOP (1)
FROM tblUsers
WHERE Username = 'Allan Chua'
using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
    if (reader.Read())
    {
        result = new User((int)reader["UserId"], reader["UserName"].ToString());
    }
}