7

私のASP.NET MVCアプリケーションでは、ドメインモデルをビューモデルから切り離しました。
viewmodelオブジェクトでエンティティを変換するので、必要なデータだけでビューを「フィード」することができます(この目的のためにvalueinjecterを使用しました)。
保存プロセス中に、コントローラがviewmodelオブジェクトを取得し、それをドメインモデルエンティティに変換し、SaveOrUpdateで永続化しようとします。 既存のレコードを更新しようとすると、Nhibernateはそれを新しいオブジェクトと見なし、エンティティが適切なIDを持っていてもINSERTを強制します。
すべてのフィールドを再度マップすることを避けたいので、前にエンティティをロード(ロード/ロード)していません。
私が間違っていることはありますか?それを達成する最良の方法は何ですか?NhibernateでSaveOrUpdateの前にエンティティをロード/取得する必要がありますか?

***** - UPDATE - ***

私のコントローラは、ユーザ(ViewModelに)を受信し、それを検証し、エンティティとしてサービス層を介して、それを保存しようと

public ActionResult Edit(Guid id, Models.User User) 
{ 
... 
var user = new Domain.User(); 
user.InjectFrom(User); 
user.SetId(id); 

user = this._SecurityService.SaveUser(user); 

} 

これはサービスです:

public Domain.User SaveUser(Domain.User User) 
     { 
      bool Result = false; 

      if (this._ValidationEngine.IsValid(User)) 
      { 
       using (_UnitOfWork) 
       { 
        if (User.Code != Guid.Empty) 
        { 
         var user = this._UserRepository.Load(User.Code); 
         user.InjectFrom(User); 
         User = this._UserRepository.Update(user); 
        } 
        else { 
         User = this._UserRepository.Save(User); 
        } 
        Result = _UnitOfWork.Commit(); 
       } 
      } 
      return (User); 
     } 

私は私のビューモデル/エンティティを何度も変えなければならないという事実を心配しています。今すぐ新しいユーザーを保存しようとすると、次のメッセージが表示されます。行が別のトランザクションによって更新または削除されました(または保存されていない値のマッピングが正しくありませんでした)
おそらくこれはDarinが私に言っていることと関係しています。
私がやろうとしていることを行うためのより良い方法はありますか?私はエラーことに気付きました

UPDATE「行が更新または削除されました...」は、私は私のマッピングのために定義されたバージョンを持っていることに起因します。私が理解できるのは、Idバージョンを、更新したいエンティティと一致させる必要があるということです。
DDD + ASP.NET MVC + NHibernateで他の人がこれらのことをどのように行うのかを理解したいですか?

SOLUTION

私のすべてのエンティティは、バージョンが定義されている(私は、申し訳ありませんと言うのを忘れて):

<version name="Version" type="System.Int32" unsaved-value="0"> 
    <column name="Version" not-null="true" /> 
</version> 

Ayendeはhereを説明したように、NHibernateのは、このようなクエリで私のエンティティを更新しよう:

UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y 

ここで、yは自分のエンティティのバージョンである必要があります。エンティティにバージョンを設定していないので、StaleObjectException例外が生成されます。
私はviewmodelにバージョンフィールドを追加しました。私はIDと一緒に私のビューの隠されたフィールドにそれを保存します。
私のコントローラは、IDとバージョンのビューモデルを受け取るようになりました。 私は(私は私のエンティティをリロードしないでください)私のドメインエンティティにこれらのフィールドを注入し、リポジトリは、それを保存してみましょう:

User = this._UserRepository.Update(user); 

私はStaleObjectException例外を取得した場合、それは他の誰かがDBの行を更新したことを意味私はユーザーにいくつかのフィードバックを提供します。

+0

エンティティを読み込んで再マップしてみてください(私はこのようにしたくないと知っています)。これを試してみてください。 – Omu

+0

私の問題はバージョンであると思います。私のマッピングに定義されている <バージョン名> "バージョン"タイプ= "System.Int32未保存値=" 0 "> <カラム名="バージョン "not-null =" true "/> – LeftyX

答えて

0

既にIDを持っているので、これがアップデートであることを知っているので、SaveOrUpdateの代わりにsession.Updateを使用してください。

+0

エンティティを保存しようとすると、このメッセージが表示されますが、同じ識別子値を持つ別のオブジェクトが既にセッションに関連付けられています:caedb8a4-abce-4c6f-b171-9e7200cc7a37 of entity :BpReminders.Domain.User – LeftyX

+0

これは、オブジェクトが既に読み込まれていることを意味します。なぜ、既に読み込まれたオブジェクトを更新していないのですか? –

+0

申し訳ありませんが間違いでした。私が今やっていることは、リポジトリからエンティティをロードし、コントローラから取得したエンティティとマージすることです。挿入しようとすると、「行が更新されたか、別のトランザクションによって削除された(または保存されていない値のマッピングが正しくありませんでした)」というエラーが表示されます。元の質問をより多くの情報で更新します。 – LeftyX

4

SaveOrUpdateが正常に動作するためには、<id>マッピングでunsaved-value属性を明示的に指定する必要があります。

<id unsaved-value="0" ... 

をしてから0とは異なる値に割り当てられたIDプロパティを持つモデルにSaveOrUpdateコールを発行し、それがUPDATE代わりのINSERTに起こっている。だから、例えば、あなたが持っているでしょう。あなたの質問に答えるために、UPDATEの前に手動でSELECTを発行する必要はありません。 SaveOrUpdateはこれをバックグラウンドで行う必要があります。

+0

大胆に感謝します。私のIDがGuid型の場合は、空のGuid(00000000-0000-0000-0000-000000000000)を使用する必要がありますね。 – LeftyX

+0

@vandalo、これを試してください:とにかく、あなたはむしろDBからエンティティを読み込んで、各フィールドに新しいエンティティを移入するべきですか(非テンポラリの場合は、 "unsaved-value =" 00000000-0000-0000-0000-000000000000 "'(未テスト)) –

+0

ca私は更新しようとしていますか?ベストプラクティスはありますか?あなたの助けをもう一度ありがとう。 – LeftyX

関連する問題