以正确的方式从SQL Server获取单个记录

Luk*_*101 7 c# sql-server sql-server-2014-express

我正在使用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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我正在使用While来遍历记录.因为while表示可能有多个记录需要迭代,我相信这可能是获取单个记录的错误方法.考虑到ADO对于一行一个字段具有ExecuteScalar,它们可能具有针对一行多个字段的指定方式.是否有指定的方法来获取ADO中的单个记录?

Dou*_*las 13

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

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.");
Run Code Online (Sandbox Code Playgroud)

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

string sql = @"SELECT TOP (2) * FROM Images WHERE id = @id"
Run Code Online (Sandbox Code Playgroud)

  • @marc_s:你不关心你得到哪两个,只要你能够确认你确实得到两个.(无论如何,你将抛出异常并丢弃它们的内容.)将Single()`转换为SQL时,Entity Framework使用相同的概念. (3认同)

Eug*_*kal 5

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

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PS:我还更改了select语句,只在select语句中选择必需的字段和包装的reader.