9

我正在使用 Ado 按 id 检索单个记录。观察:

public async Task<Image> GetImage(int id)
{
    var image = new Image();

    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        conn.Open();

        string sql = @" SELECT * FROM Images where id = @id";

        using (SqlCommand comm = new SqlCommand(sql, conn))
        {
            comm.Parameters.AddWithValue("@id", id);

            var reader = await comm.ExecuteReaderAsync();

            int ordId = reader.GetOrdinal("id");
            int ordName = reader.GetOrdinal("name");
            int ordPath = reader.GetOrdinal("path");

            while (reader.Read())
            {
                image.Id = reader.GetInt32(ordId);
                image.Name = reader.GetString(ordName);
                image.Path = reader.GetString(ordPath);
            }

            return image;
        }
    }
}

如您所见,我正在使用 While 来遍历记录。由于 while 表示可能有不止一个记录需要迭代,我相信这可能是获取单个记录的错误方法。考虑到 ADO 对一行一个字段有 ExecuteScalar,也许他们对一行多个字段有一个指定的方式。是否有指定的方法来获取 ADO 中的单个记录?

4

3 回答 3

16

我会采用你目前的方法,除了我会消除 while 循环。如果要确保只返回一条记录,请执行额外的Read操作以确保它返回 false。这类似于 LINQSingle运算符的语义。

if (!reader.Read())        
    throw new InvalidOperationException("No records were returned.");

image.Id = reader.GetInt32(ordId);
image.Name = reader.GetString(ordName);
image.Path = reader.GetString(ordPath);

if (reader.Read())
    throw new InvalidOperationException("Multiple records were returned.");

假设id你的数据库中的列是主键(唯一),则不需要TOP在 SQL 查询中指定子句;SQL Server 查询优化器会推断出由于该WHERE子句最多只返回一条记录。但是,如果您在列上没有主键或唯一索引/约束id,那么您应该发出一个TOP (2)子句来限制返回的行数。您应该避免使用TOP (1),因为您将无法检测(并引发错误)额外的匹配。

string sql = @"SELECT TOP (2) * FROM Images WHERE id = @id"
于 2015-04-25T12:16:35.463 回答
6

如果您只阅读一次怎么办:

using (SqlConnection conn = new SqlConnection(ConnectionString))
{
    conn.Open();

    string sql = @" SELECT id, name, path FROM Images where id = @id";

    using (SqlCommand comm = new SqlCommand(sql, conn))
    {
        comm.Parameters.AddWithValue("@id", id);           

        using (var reader = await comm.ExecuteReaderAsync())
        {
            if (!reader.Read())
                 throw new Exception("Something is very wrong");

            int ordId = reader.GetOrdinal("id");
            int ordName = reader.GetOrdinal("name");
            int ordPath = reader.GetOrdinal("path");

            image.Id = reader.GetInt32(ordId);
            image.Name = reader.GetString(ordName);
            image.Path = reader.GetString(ordPath);

            return image;
        }
    }
}

PS:我还更改了选择语句以仅选择必填字段并将阅读器包装在 using 语句中。

于 2015-04-25T12:16:53.540 回答
3

在这种情况下,您可以Top(1)在查询中使用以仅从数据库中获取单个记录:

SELECT Top(1) * FROM Images 
where id = @id
order by id desc -- will get the latest record
于 2015-04-25T12:16:40.667 回答