6
using (var transaction = new TransactionScope())
{
     using (var db = new MyEntities())
     {    
          var newGroup = new Groups
          {
              GroupDate = DateTime.Now,
              GroupName = "someName"
          };
          db.Groups.Add(newGroup);
          db.SaveChanges();
     }
     transaction.Complete();
 }

GroupId と GroupDate は PK、GroupId は Identity (ステップ = 1)、GroupDate はそうではありません

このような単純なコードを使用したときにこの例外が発生した理由と、可能であれば楽観的同時実行更新をオフにする方法を教えてください。

Store update、insert、または delete ステートメントが予期しない数の行 (0) に影響を与えました。エンティティが読み込まれてから、エンティティが変更または削除された可能性があります。ObjectStateManager エントリを更新します。

4

2 に答える 2

10

おそらく、.NETDateTime型と SQL Server で使用している列型の精度が異なることに問題があると思われますdatetime

データベースに送信される INSERT ステートメントはSaveChanges次のようになります。

exec sp_executesql N'insert [dbo].[Groups]([GroupDate], [GroupName])
values (@0, @1)
select [GroupId]
from [dbo].[Groups]
where @@ROWCOUNT > 0 and [GroupId] = scope_identity() and [GroupDate] = @0',
N'@0 datetime2(7),@1 nvarchar(50)',
@0='2013-09-01 14:21:44.5156250',@1=N'someName'

.NETDateTimeは小数点以下 7 桁を格納します: .5156250. ただし、SQLdatetime型は精度が低く、値を格納した後に一部の桁が切り捨てられるため、これを格納できません。[GroupDate] = @0したがって、where句の比較が返されfalse、EF は何も格納されていないという情報を取得し (ただし、INSERT は実際に実行されいます)、トランザクションをキャンセルして例外をスローします。

私が見る限り、この問題は次の変更のいずれかによってのみ解決できます。

  • 主キーから削除GroupDateします。つまり、非キー列にします。
  • または、.NET型datetime2(7)と同じ精度を持つSQL Server の列の型を変更します。DateTime
  • または、GroupDate精度を低くして、値が途切れることなく SQL 型に完全に格納できるようにしますdatetime。たとえば、秒の精度とミリ秒のみを使用します0

    var now = DateTime.Now;
    var date = new DateTime(now.Year, now.Month, now.Day,
                            now.Hour, now.Minute, now.Second);
    
    var newGroup = new Groups
    {
        GroupDate = date,
        GroupName = "someName"
    };
    

    (上記のコードよりも、指定された値からミリ秒を削除するスマートな方法があるかもしれませんが、DateTime今のところ見つけられませんでした。)

于 2013-09-01T12:38:21.010 に答える
1

Optmistic Concurrency Updatesをオフにしないでください。問題が隠され、修正されません。以下をせよ:

using (var db = new MyEntities())
{    
    using (var transaction = new TransactionScope())
    {
        var newGroup = new Groups
        {
            GroupDate = DateTime.Now,
            GroupName = "someName"
        };
        db.Groups.Add(newGroup);
        db.SaveChanges();
        transaction.Complete();
     }
}

DBContext 内で TranscationScope を作成しているのとは異なり、これで問題が解決することを願っています。

于 2013-09-01T11:16:13.973 に答える