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を使用してレコードを繰り返し処理しています。が意味している間、反復する複数のレコードがあるかもしれないので、これは単一のレコードを取得するための間違った方法かもしれないと思います。 ADOが1行1フィールドのExecuteScalarを持っていることを考慮してください。それらは1行の複数フィールドに対して指定された方法を持っているかもしれません。ADOで単一のレコードを取得するための指定された方法はありますか?
Whileループを排除することを除いて、私はあなたの現在のアプローチを採用します。確実に1つのレコードのみが返されるようにする場合は、追加の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.");
_
データベースのid
列が主キー(一意)であると想定すると、SQLクエリでTOP
句を指定する必要はありません。 SQL Serverクエリオプティマイザーは、WHERE
句が原因で最大で1つのレコードのみが返されると推定します。ただし、id
列に主キーまたは一意のインデックス/制約がない場合は、TOP (2)
句を発行して、返される行の数を制限する必要があります。余分な一致を検出(およびエラーを発生)できないため、TOP (1)
の使用は避けてください。
_string sql = @"SELECT TOP (2) * FROM Images WHERE id = @id"
_
一度だけ読んだ場合:
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.: selectステートメントを変更して、必要なフィールドのみを選択し、ステートメントを使用してリーダーをラップしました。
この場合、クエリで Top(1)
を使用して、データベースから単一のレコードのみを取得できます。
SELECT Top(1) * FROM Images
where id = @id
order by id desc -- will get the latest record