0

私のシステムはデータベースファースト、EF4.3.1です。

PKが2つのint列と日時で構成されているテーブルがあります。このテーブルは、コメントを保持するための「コメント」テーブルです。

CREATE TABLE [dbo]。[ArticleComments](
    [ArticleId] [int] NOT NULL、
    [UserId] [int] NOT NULL、
    [MessageText] [nvarchar](max)NOT NULL、
    [CreatedAt] [datetime] NOT NULL、
    [ExternalData] [bigint] NULL、
    CONSTRAINT[PK_ArticleComments]主キーがクラスター化されました
    ((
       [ArticleId] ASC、
       [UserId] ASC、
       [CreatedAt] ASC
    )。
)。

私のロジックでは、コメントが作成されると、ArticleCommentオブジェクトを別のスレッドに送信します。このスレッドでは、オブジェクトに対して追加のアクションを実行するために別のコンテキストが開かれ、最終的にオブジェクトが保存される可能性があります。

問題は、オブジェクトが後で保存されるときに、何も保存されていないという例外がスローされる場合があることです。

プロファイラーを開いて、どのSQLが実行されているかを確認しましたSaveChanges()

exec sp_executesqlN'update[dbo]。[ArticleComments]
set [ExternalData] = @ 0
ここで、((([ArticleId] = @ 1)and([UserId] = @ 2))and([CreatedAt] = @ 3))
'、N' @ 0 bigint、@ 1 int、@ 2 int、@ 3 datetime2(7)'、@ 0 = 3243423、@ 1 = 6931、@ 2 = 2、@ 3 ='2012-10-11 11: 23:25.4734801 '

そして、問題はEFが通常の日時ではなくdatetime2(7)にマッピングしていたことであることがわかりました。そのため、この更新では何も変更されず、例外がスローされます。

EDMXファイルを確認しましたが、そのタイプは精度3の日時であると表示されています。

参考:さらに、SQLServerでは日時が丸められます

だから、私はこの記事を見つけました:.NET DateTimeミリ秒を丸めるので、SQLServerミリ秒に合わせることができます 。これは.net時間をSQL時間に丸める良い方法を示しています。そして、同じことを行う、Microsoft®SQLServer®2012のMicrosoft®SystemCLRTypesのフレームワーク にこのためのクラスがあると思います。System.Data.SqlTypesSqlDateTime

したがって、私のコードは次のようになります(リンクされたSO回答の拡張機能を使用):

時間をハックする->message.CreatedAt= message.CreatedAt.RoundToSqlServerDateTime();
                    db.ArticleComments.Attach(message);
                    message.ExternalData = someNumber;
                    db.SaveChanges();

そしてそれは動作します。

しかし、これらはすべてハックであり、解決策ではありません。EFがここで失敗するのはなぜですか、私は間違って何をしていますか?

4

0 に答える 0