Get a single record from SQL Server the correct way

老子叫甜甜 提交于 2019-12-03 13:52:40

I would go with your current approach, except that I'd eliminate the while loop. If you want to ensure that only one record is returned, perform an extra Read to ensure it returns false. This is similar to the semantics of the LINQ Single operator.

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

Assuming that the id column in your database is a primary key (unique), there is no need to specify a TOP clause in the SQL query; the SQL Server query optimizer would deduce that only at most one record is returned due to the WHERE clause. However, if you don't have a primary key or unique index/constraint on the id column, then you should issue a TOP (2) clause to restrict the number of returned rows. You should avoid using TOP (1) because you would be unable to detect (and raise an error for) extra matches.

string sql = @"SELECT TOP (2) * FROM Images WHERE id = @id"

What if you just read once:

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

P.S.: I have also changed select statement to select only required fields and wrapped reader in using statement.

You can use Top(1) in this case in your query to get only single record from database:

SELECT Top(1) * FROM Images 
where id = @id
order by id desc -- will get the latest record
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!