2

テーブル名と列名を受け取り、指定された列でソートされたそのテーブルから行をフェッチし、それらに対して何らかの処理を行う、繰り返し構成可能なタスクがあります。最後に、注文列の最後の値を保存して、再開したときにその時点以降の行のみを処理するようにします。

その情報を保存するために、いくつかの識別情報(テーブル名など)と注文列の最後の値を文字列として含む別のテーブルがあります。このテーブルを操作するために、私は次のようなことをしました。

public T GetValue<T>(ProgressRecord<T> record) {
    string value = GetValueAsString(record); // this calls a sproc that fetches the value; the record fields are used as a filter
    return value != null ? (T)Convert.ChangeType(value, typeof(T)) : default(T);
}

public void SetValue<T>(ProgressRecord<T> record) {
    string value = Convert.ToString(record.value);
    InnerSetValue(record, value); // this calls a sproc that saves the value; the record fields are used as a filter
}

ここでProgressRecord、識別情報と値は次のように含まれますT

default(T)なぜなら、値がまだ存在しない場合は、そのタイプのデフォルト値を、行をフィルタリングするための開始値として使用するためです。

これは数値タイプでは問題なく機能しますが、にはいくつかの問題がありますDateTime

1つ目はConvert.ToString(DateTime)、ミリ秒の情報を保持しないことです。同じ行を再度処理しないようにするために必要です(01:23:42.578の場合、01:23:42.000からフィルタリングします。それらを再度フェッチします)。

2つ目は、default(DateTime)が0001年1月1日の日付を返すことです。その日付を返送して、それより大きい日付の行をフェッチしようとすると、MSSQLは日付が範囲外であると文句を言います。 1753年1月1日以降。

そこで、コードを次のように変更しました。

public T GetValue<T>(ProgressRecord<T> record) {
    string value = GetValueAsString(record); // this calls a sproc that fetches the value; the record fields are used as a filter
    if (value != null) {
        T returnVal = (T)Convert.ChangeType(value, typeof(T));
        if (typeof(T) == typeof(DateTime)) {
            returnVal = (T)Convert.ChangeType(DateTime.ParseExact(value, "yyyy-MM-dd hh:mm:ss.fff"));
        }
        return returnVal;
    }
    T defaultVal = default(T);
    if (typeof(T) == typeof(DateTime)) {
            defaultVal = (T)Convert.ChangeType(SqlDateTime.MinValue.Value, typeof(T));
    }
    return defaultVal;
}

public void SetValue<T>(ProgressRecord<T> record) {
    string value = Convert.ToString(record.value);
    if (typeof(T) == typeof(DateTime)) {
        value = record.value.ToString("yyyy-MM-dd hh:mm:ss.fff");
    }
    InnerSetValue(record, value); // this calls a sproc that inserts/updates the value; the record fields are used as a filter
}

IFのせいで、このコードはちょっと汚いです。タイプチェックに頼らずに、これらの変換を行うためのより簡単な方法はありますか?これを行う方法を知っている、見逃したシステムクラスはありますか?日付をミリ秒単位の文字列に変換し、nullのカスタムデフォルト(SQLDateTime.MinValue)を提供しますか?

4

2 に答える 2

0

標準Convert.ToString(DateTime value)は単に呼び出していますvalue.ToString()

DateTime.ToString()実際に呼び出しています

DateTimeFormat.Format(this, null, DateTimeFormatInfo.CurrentInfo)

したがって、基本的に、特定のdtfiを使用してカルチャ設定を変更すると、最後にミリ秒でデフォルトの形式を設定できるため、最初の問題を回避できると思います。

2番目の問題については、エレガントな方法でオーバーライドできるかどうかわかりません。値をデータベースに更新する前に、値がに等しいかどうかを確認できますDateTime.MinValue。または、それほどエレガントではない場合は、以下のコードを実行して、それを実行したのがあなたであることが誰にもわからないことを願っています。

typeof(DateTime).GetField ("MinValue").SetValue (typeof(DateTime), new DateTime(1753, 1, 1));
于 2012-12-15T15:46:51.660 に答える
0

あなたの仕事を達成する2つの方法があります:

  1. データベース クエリでは、秒に丸められた日時を使用します。つまり、処理する行セットの最後のレコードが 01:23:42.578 の場合、それを無視して 01:23:42.000 までのすべてのレコードを処理します。これは、次の処理のために残しておくことを意味します。次に、構成情報テーブルに最後に処理された日時値として 01:23:42.000 を保存します。次に処理を実行すると、01:23:42.000 から始まるすべてのレコードが取得されます。これには、前回の実行で取得されたはずの 01:23:42.578 のレコードが含まれます。
  2. Ticks2 番目の解決策では、型の場合はプロパティ を使用しますDateTime
于 2012-12-15T15:54:21.967 に答える