2016-06-28 95 views
0

私はMVCのEFで新しくなっています。私は、アプリケーションで同時性チェックを実装する必要があります。cshtmlページの 'TimeStamp'変数をAJAXコール経由でコントローラに渡します

私は並行処理がEFに処理するためのビルトイン対応無しに関するMSDNヘルプを以下ました:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application

しかし、私の場合、私は部分的な更新をやっているので、私は、サーバー側を呼び出すためにAJAXを使用していますそれを行う方法。このサーバーサイドのメソッドでは、並行性チェックを実装する必要があります。 Entityクラスで

ALTER TABLE dbo.Job 
ADD RowVersion rowversion NULL; 

:私の中

[Timestamp] 
public byte[] RowVersion { get; set; } 

私はタイムスタンプ列を作成し、私のDBで

まず:私は私のコードでは、必要な変更を加えたチュートリアル後

マッピングクラス(流暢なAPIを使用):

this.Property(t =>  
    t.RowVersion).HasColumnName("RowVersion").IsConcurrencyToken(); 
私のコントローラで最後に

function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) { 
    var hdnJobId = $("#JobId").val(); 
    //var hdnRowVersion = $("#RowVersion").val(); 
    var hdnAccountingId = $("#hdnAccountingSystemId").val(); 
    $.ajax(
      { 
       type: "GET", 
       url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"), 
       dataType: "json", 
       contentType: "application/json; charset=utf-8", 
       data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId },//,rowVersion: hdnRowVersion }, 
       success: function (data) { 
        GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId); 
       }, 
       error: function (result) { 

       } 
      }); 

} 

(上:JSファイル(AJAX呼び出し)で

@Html.HiddenFor(x => x.RowVersion) 

:3210 私の見解モデルクラスで

:私のビューファイルで

[Timestamp] 
public byte[] RowVersion { get; set; } 

私のajax呼び出し): MSDN(using System.Data.Entity.Infrastructure;)の名​​前空間を追加しました

ここ
[System.Web.Http.HttpGet] 
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction, 
    int jobTransferStatusId, short accountingSystemId, byte[] rowVersion) 

私は関係なく、常に私はAJAX呼び出しかでのparamとして値を送信した場合の、「byte[] rowVersion」の「null」を取得しています(私はここに貼り付けたことを、私のコードスニペットにコメントに保管しました)。

成功した挿入/更新の実行ごとにDBで列が更新されていることを確認しました。また、ビューモデルは各ページの負荷でこのRowVersion列のDBから最新の値を取得しています。

MSDNの例では、フォームを提出しましたが、私はAJAX呼び出しを使用していますが、すべての面を同じにしていました。

ビューモデルオブジェクト全体を送信すると私の仕事をするかもしれませんが、オブジェクト全体を部分的に更新する必要はありません。

rowVersionをajaxコールに渡すにはどうすればよいですか?

+0

ありがとうポール、私はそれを提出した直後にフォーマットミスを認識しましたが、私よりも速かったです。 :D –

答えて

1

文字列として送信し、サーバー上のバイト配列に変換する必要があります。これは、HTMLページがinputタグ(hidden型)の文字列としてbase64形式で格納するためです。 C#側のわずかな変更は、それを修正する必要があります。

ビュー:

byte[]が渡されたとき、あなたの既存のコード、 HiddenForのデフォルトの動作に必要な変更は

C#コード

[System.Web.Http.HttpGet] 
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction, int jobTransferStatusId, short accountingSystemId, string rowVersion){ 
    var rowVersionBytes = System.Convert.FromBase64String(rowVersion); // convert to byte array 
} 

にベース64文字列にJavascriptを、それを変換することはありません

function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) { 
    var hdnJobId = $("#JobId").val(); 
    var hdnRowVersion = $("#RowVersion").val(); // this will be a string 
    var hdnAccountingId = $("#hdnAccountingSystemId").val(); 
    $.ajax(
     { 
      type: "GET", 
      url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"), 
      dataType: "json", 
      contentType: "application/json; charset=utf-8", 
      data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId, rowVersion: hdnRowVersion } 
      success: function (data) { 
       GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId); 
      }, 
      error: function (result) { 
      } 
     }); 
} 

最後に実際に更新を実行しているため、これはHttpPostまたはHttpPutであり、HttpGetではないはずです。

  • HttpGetは、データを取得し、データが変更されていない場合にのみ使用してください。
  • HttpPutは、同一の予期される結果(これは冪等とも呼ばれます)で複数回同じ修正を呼び出すことができる場合に使用します。これは通常更新に使用されます。
  • はHttpPost同じコールが(サーバー上または応答中のいずれか)が呼び出されるたびに異なる結果になりますときに使用する必要があり、これはusualyのために使用されている が作成

私は見ます既存のデータに予期しない問題が発生する可能性があります。 タイプが指定されている場合、カラムRowVersionにはNOT NULLとマークする必要があります.Sql Serverは既存のすべてのレコードに値を設定します。

ALTER TABLE dbo.Job 
ADD RowVersion rowversion NOT NULL 
+1

タイムスタンプをbase64としてシリアル化する方が良いのではないでしょうか?タイムスタンプのバイトのいずれかがUTF8の範囲外にあった場合、そこにあるものは動作しません。 –

+0

@MikeMcCaughan - それは可能でしょうか? 'rowversion 'は8バイトで構成されています(それぞれ0〜255の値を持ちます)。私はUTF8が1つのutf8文字が1〜4バイトのサイズになることがあるので、これに問題があるとは思わない。しかし、ControllerとViewの両方で明示的に同じ変換を指定することは悪い考えではないので、バイト配列の変換に使用されるフォーマットについて混乱はありません。私の答えを更新させてください。 – Igor

+0

さて、** Jon Skeetは(言い換え)、[自分自身の文字列ではない任意のバイトをエンコードするために文字列を使うべきではありません](http://stackoverflow.com/a/7997022/215552)。 –

関連する問題