0

ユーザーが「ティック」を記録する小さなサービスを作成しています。いくつか問題があります。ユーザーは 1 日に 1 回以上ログを記録できないはずです。そのチェックのための私のSQLは次のとおりです。

using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.Connection = conn;
                        cmd.CommandText = "SELECT * FROM TickLog WHERE Username = @username AND DATEPART(year, Inserted) = DATEPART(year, @date) AND DATEPART(month, Inserted) = DATEPART(month, @date) AND DATEPART(day, Inserted) = DATEPART(day, @date)";
                        cmd.Parameters.AddWithValue("@username", username);
                        cmd.Parameters.AddWithValue("@date", DateTime.Now);

                        int affectedRows = cmd.ExecuteNonQuery();

                        if (affectedRows > 0)
                            throw new Exception("allready registered");
                    }

テーブルの構造は非常に簡単です。

  • ID、整数
  • ユーザー名、文字列
  • 挿入日
4

2 に答える 2

2

ExecuteNonQuery()UPDATE、INSERT、または DELETE によって影響を受けた行の数を返します。Select を実行しているだけなので、常に 0 の影響を受ける行が返されます。ExecuteReader()を使用して、返された結果に値があるかどうかを確認してみてください。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx http://msdn.microsoft.com/en-us/library/9kcbe65k.aspx

または、クエリを に変更してSELECT COUNT(*)...を使用することもできますExecuteScalar()。これにより、見つかった行数が返されObjectます ( にキャストできるとしてint)。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx

于 2013-03-21T13:07:12.357 に答える
1

これは機能し、パフォーマンスがわずかに向上します。

using (var cmd = new SqlCommand())
{
    cmd.CommandText = @"CASE
        WHEN EXISTS (
            SELECT
                *
            FROM
                TickLog TL
            WHERE
                TL.Username = @username
                AND TL.Inserted BETWEEN @date AND DATEADD(DAY, 1, DATEADD(MILLISECOND, -3, @date))
            ) THEN 1
        ELSE 0
    END";

    cmd.Parameters.AddWithValue("@username", username);
    cmd.Parameters.AddWithValue("@date", DateTime.Date);

    var exists = cmd.ExecuteScalar();

    if (exists != 0)
    {
        throw new Exception("already registered");
    }
}

説明:

  • EXISTSデータベースからレコード全体を取得する必要はありません。
  • TL.Insertedインデックス付きの列である必要がありますが、使用するDATEPART場合はインデックスを使用しません。

-3 ミリ秒を使用する理由については、このStackOverflow の回答とこのブログ投稿を参照してください。

于 2013-03-21T13:36:16.873 に答える