2017-01-09 2 views
0

私は、Entity Framework用のAPIベースの実装を使用しています。 EFオブジェクトは、クライアントに送信される前にDTO(データ転送オブジェクト)にキャストされます。db.Entryをチェックするまで、ObjectStateEntryは更新されません。

途中で、私はDTOから私のエンティティタイプに戻っています。 DELETE/UPDATE呼び出しで並行性チェックに問題があります。私はEF 6とwebAPI 2を使用しています。

実際には、データベースからオブジェクトをロードした後、オブジェクト状態エントリが実際に 'Modified'に変更される前にdb.Entry(オブジェクト)を呼び出す必要があります。 。

コード:

[Route("")] 
    [HttpDelete] 
    [ResponseType(typeof(void))] 
    public async Task<IHttpActionResult> DeleteAssetType(long id, DateTimeOffset modifyDate) 
    { 
     try 
     { 
      AssetType assetType = await db.AssetTypes.FindAsync(id); 
      if (assetType == null) 
      { 
       return NotFound(); 
      } 

      //Set modifyDate to match what API received and then mark record for deletion 
      ObjectStateEntry ose = ((IObjectContextAdapter) db).ObjectContext.ObjectStateManager.GetObjectStateEntry(assetType); 
      assetType.ModifyDate = modifyDate; 
      ose.AcceptChanges(); 
      db.AssetTypes.Remove(assetType); 

      try 
      { 
       await db.SaveChangesAsync(); 
      } 
      catch (DbUpdateConcurrencyException) 
      { 
       //TODO Handle Concurrency Exception Specifically (if needed) 
       throw; 
      } 
     } 
     catch(Exception ex) 
     { 
      //TODO Add Error Handling Code 
      throw; 
     } 

     //return Ok(assetType); 
     return Ok(); 
    } 

...と、問題は、私はose.Stateを見れば、コールassetType.ModifyDate = modifyDate(これは私の並行処理パターンである)の後に、それは "変更なし" だ、ということです。しかし、デバッガを介してdb.Entry(assetType)を参照すると、oseがoseを参照すると、oseは正しく「Modified」と表示します。

コアの問題は、ose.AcceptChanges()を呼び出すとオブジェクトが未変更として認識されるため、何もしないということです。

これはdb.Entry(assetType)を呼び出すだけで、結果として得られるオブジェクトは何も表示されず、その点からは完璧に機能しますが、これは別の場所で何か間違ったことを示唆しているようですFindAsyncはエンティティをコンテキストに結びつけていると主張しているので、状態を要求する前に.Entryを呼び出す必要はありません。私がしなければ、私が何を意味するかの拡張例として

、以下:

... 
assetType.ModifyDate = modifyDate; 
var state = db.Entry(assetType).State; /* ADDED THIS LINE */ 
ose.AcceptChanges(); 
.... 

を... ose.AcceptChangesに、その後の呼び出し()私が期待するまさにありません。私の質問/問題は、システムが変更されたオブジェクトを参照できるようにするためにdb.Entry(assetType)を呼び出さなければならないのですか?以前はFindAsync経由でコンテキストにアタッチされていないのですか?また、自動的にmodifyDateへの変更を受け取らないのでしょうか?重要なのは、最初のコードではなく、edmxファイルのdb-firstです。

EDIT:Delete API関数の完全なコードを含むように変更されました。

EDIT 2:明確化されたもの私は何を求めているか/この仕事をする/何を問題にしていますか?

答えて

0

はこれを試してみてください:

AssetType assetType = await db.AssetTypes.FindAsync(id); //get object from db 
assetType.ModifyDate = modifyDate; //modify it 
var state = db.Entry(assetType).State; //get current state, which should be Modified 
var updatedRecords = await db.SaveChangesAsync(); 

問題は、任意の変更がエンティティに行われた前に取得した状態だったということのようです。 ところで、メソッドRemove(https://msdn.microsoft.com/en-us/library/gg679171(v=vs.113).aspx)はエンティティを削除済みとしてマークしていますので、それはあなたが望むものではないと思います。

+0

これは、状態が「変更済み」と言う意味で機能します。私が苦労している問題は、私が「削除」を意味するということです。私がしたいのは、データベースのmodify-dateフィールドがAPIが受け取ったものと一致する場合、データベースからオブジェクトを削除することです。 質問を変更して少し明確にします。問題は、呼び出しの結果に関係なく、db.Entry(assetType)を呼び出す必要があります。状態は実際に正しく設定されています。 – SooperGenius

関連する問題