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が1行1フィールドに対してExecuteScalarを持っていることを考えると、1行複数フィールドに対して指定された方法があるかもしれません。ADO で単一のレコードを取得する特定の方法はありますか?

4

3 に答える 3

16

whileループを排除することを除いて、私はあなたの現在のアプローチを採用します。確実に 1 つのレコードのみが返されるようにする場合は、 Readfalse を返すように追加の操作を実行します。これは、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.");

データベースの列が主キー (一意) であると仮定すると、SQL クエリで句idを指定する必要はありません。SQL Server クエリ オプティマイザーは、この句TOPによって返されるレコードは多くても 1 つだけであると推測します。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: select ステートメントも変更して、必要なフィールドのみを選択し、リーダーを 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 に答える