2016-07-26 22 views
3

を強制されていない私はここにドキュメントを追ってきた、と私はVersionColという名前の私のテーブルにタイムスタンプ列を追加して、ときに私きたのSQL Server 2016(https://ef.readthedocs.io/en/latest/modeling/concurrency.htmlEFコア同時実行が

を使用していますScaffold-DbContextを実行すると、DbContextのテーブルエンティティに次のプロパティが設定されます。

entity.Property(e => e.VersionCol) 
    .IsRequired() 
    .HasColumnType("timestamp") 
    .ValueGeneratedOnAddOrUpdate() 

それはので、私は自分自身にそれを追加しましたが、それでも例外が並行性の問題を受けなければならない状況でスローされません.IsConcurrencyToken()が欠落しています。代わりに単にデータを上書きします。

紛失しているものがありますか?

編集:

私はデータベース-最初のアプローチ(これなし[タイムスタンプ]または任意の他の注釈)を使用していて、私のDbContextはStartup.cs

services.AddScoped<IPoRepository, PoRepository>()で構成され、サービスの中に注入されています

私のモデルにはpublic byte[] VersionCol { get; set; }というフィールドが生成されています。私PoRepositoryで

私は次のように私のポーを更新しようとしている:

public void SavePo(PoListing poListing) { 
    Po po; 

    try { 
     po = _context.Po.Where(p => p.Poid == poListing.PoId).First(); 
    } catch (ArgumentNullException) { 
     throw new ArgumentNullException("The PO does not exist."); 
    } 

    po.AssignedUserId = poListing.AssignedUserId; 
    po.VersionCol  = poListing.VersionCol; 

    _context.Entry(po).State = EntityState.Modified; 

    _context.SaveChanges(); 
} 

それだけ(それは、テーブルそれの列の一部ではありませんしているのでPoListingは、基本的にポーのほんの一部であり、データベースに格納されています)、最初に生成されたときにPoのVersionColを持ちます。 PoListingのPoCよりも古いVersionColがある場合は、例外が発生するはずです。

EDIT2:

これは動作しますが、私はそれがこの第二のコンテキストを作るために必要とせずに動作させる、とばかりに注入コンテキストを使用する方法を見つけ出すことはできません。

public void SavePo(PoListing poListing) { 
    DbContextOptionsBuilder<TMS_1000Context> options = new DbContextOptionsBuilder<TMS_1000Context>(); 
    options.UseSqlServer("Server=DEVSQL16;Database=TMS_1000_Dev;Trusted_Connection=True;MultipleActiveResultSets=true"); 

    TMS_1000Context context1; 

    try { 
     po = _context.Po.Where(p => p.Poid == poListing.PoId).First(); 
    } catch (ArgumentNullException) { 
     throw new ArgumentNullException("The PO does not exist."); 
    } 

    using (context1 = new TMS_1000Context(options.Options)) { 
     po.AssignedUserId = poListing.AssignedUserId; 
     po.VersionCol = poListing.VersionCol; 

     context1.Update(po); 

     context1.SaveChanges(); 
    } 
} 

EDIT3:

これが現在取り組んでいます。別の方法がありますか? EFコア追跡は元の値がデータベースに現在何があるかと同じである場合にのみ気に、彼らはそれからでない場合は、同時実行例外がスローされたときにそれはだから

public void SavePo(PoListing poListing) { 
    Po po; 

    try { 
     po = _context.Po.Where(p => p.Poid == poListing.PoId).First(); 
    } catch (ArgumentNullException) { 
     throw new ArgumentNullException("The PO does not exist."); 
    } 

    po.AssignedUserId = poListing.AssignedUserId; 

    _context.Entry(po).Property(u => u.VersionCol).OriginalValue = poListing.VersionCol; 

    _context.Update(po); 
    _context.SaveChanges(); 
} 
+1

と同様の機能は、あなたがのDataContextに渡すなかったものを、私はどのようにあなたがあなたのエンティティを更新しない平均たちを示していただけますか? –

+1

詳細情報を追加できますか?コードファーストモデルやDbContextの 'OnModelCreating'メソッドに' [Timestamp] '属性を追加していますか、既存のデータベースから足場をはじめてデータベース化する方法を試していますか?あなたのモデルとDbContextコードを少なくとも関連する 'OnModelCreating'に投稿してください。 – Tseng

+0

私は詳細を追加しました。あなたが見たいものがあれば教えてください。 – GlacialFlames

答えて

0

私はこれが起こっていると考えている理由があります。

ここに3つの修正があります。

  1. 元の値がデータベースに存在する値と異なるように変更します。

    public void SavePo(PoListing poListing) { 
        Po po; 
    
        try { 
         po = _context.Po.Where(p => p.Poid == poListing.PoId).First(); 
        } catch (ArgumentNullException) { 
         throw new ArgumentNullException("The PO does not exist."); 
        } 
    
        po.AssignedUserId = poListing.AssignedUserId; 
    
        _context.Entry(po).Property(u => u.VersionCol).OriginalValue = poListing.VersionCol; 
    
        _context.Update(po); 
        _context.SaveChanges(); 
    } 
    
  2. エンティティをAsNoTracking()で取得します。現在、EF Coreは元の値を比較するだけではありません。

    public void SavePo(PoListing poListing) { 
        Po po; 
    
        try { 
         po = _context.Po.AsNoTracking().Where(p => p.Poid == poListing.PoId).First(); 
        } catch (ArgumentNullException) { 
         throw new ArgumentNullException("The PO does not exist."); 
        } 
    
        po.AssignedUserId = poListing.AssignedUserId; 
        po.VersionCol  = poListing.VersionCol; 
    
        _context.Update(po); 
        _context.SaveChanges(); 
    } 
    
  3. コンテキストからエンティティを切り離します。修正#2

    public void SavePo(PoListing poListing) { 
        Po po; 
    
        try { 
         po = _context.Po.Where(p => p.Poid == poListing.PoId).First(); 
        } catch (ArgumentNullException) { 
         throw new ArgumentNullException("The PO does not exist."); 
        } 
    
        po.AssignedUserId = poListing.AssignedUserId; 
        po.VersionCol  = poListing.VersionCol; 
    
        _context.Entry(po).State = EntityState.Detached; 
    
        _context.Update(po); 
        _context.SaveChanges(); 
    }