3

簡単にするために、次のようなSQLServerCEテーブルがあるとしますWidgets

create table [Widgets] (
  [Id] int not null primary key,
  [Created] datetime not null default getdate())

Created列の値を指定せずに挿入すると、期待どおりに機能します。

insert into [Widgets] ([Id]) values (1)

と呼ばれるEntityFrameworkモデルを生成した後、Database次のコードを記述します。

Database db = new Database();
db.Widgets.AddObject(new Widget { Id = 2 });
db.SaveChanges();

しかし、それは例外を引き起こします: EFが列をnull許容ではないとAn overflow occurred while converting to datetime.見なすという事実までこれを追跡したので、newが構築されると、そのプロパティはデフォルト(0001-01-01 12:00:00 )に設定されます)、これはSQLServerCEの有効範囲外です。CreatedDateTimeWidgetCreatedDateTime

では、上記のC#のサンプルを機能させるにはどうすればよいですか?データベーススキーマを変更したくない。CreatedコンストラクターでプロパティをDateTime.Nowに設定できることはわかっていますWidgetが、aが作成されてから実際にデータベースに挿入されるまで、数分かかる場合がWidgetあります。これは、実際にキャプチャしたい時間です。

更新:とに設定しようとしStoreGeneratedPatternましIdentityComputedが、例外が発生します:Server-generated keys and server-generated values are not supported by SQL Server Compact。デフォルト値はSQLServerCEで機能するため、EntityFrameworkの制限である必要があります。(どうやらこれはSQL Server CE 4.0で修正されています。)

4

2 に答える 2

2

DanMの関連する質問リンクは、変更の追跡に向けて正しい方向を示しているようです。次のコードは、私が探している動作にかなり近づきます。

public partial class Database
{
  public override int SaveChanges(SaveOptions options)
  {
    foreach(var w in this.ObjectStateManager
                         .GetObjectStateEntries(EntityState.Added)
                         .Where(e => e.Entity is Widget)
                         .Select(e => (Widget)e.Entity))
    {
      if(w.Created == default(DateTime))
        w.Created = DateTime.Now;
    }

    return base.SaveChanges(options);
  }
}

すべてのWidgetsのCreated値は、現在の日付と時刻に設定されます。私が見る他の唯一の問題は、値がサーバーではなくクライアントの時計に従って設定されていることです。また、一度に多くの行を挿入する場合、タイムスタンプは通常の挿入の場合よりも少し早くなります。

最善の解決策は、SQL Serverが構成されていることを実行できるようにすることです。提供されていない場合は、列の値を設定します。C'estlavie。

于 2012-04-27T16:41:59.977 に答える
1

Widget部分クラスのCreatedプロパティをそのコンストラクターで設定できます。

public partial class Widget
    {
        public Widget()
        {
            this.Created = System.DateTime.Now;
        }
    }
于 2012-04-27T04:00:59.117 に答える