7

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

***** - アップデート - ***

私のコントローラーはユーザー(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);
        }

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

アップデート

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

解決

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

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

Ayende がここで説明したように、Nhibernate は次のようなクエリでエンティティを更新しようとします。

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

ここで、y はエンティティのバージョンです。エンティティにバージョンを設定していなかったため、例外 StaleObjectException が生成されました。
ビューモデルにバージョン フィールドを追加しました。ビューの非表示フィールドに ID とともに保存します。
私のコントローラーは、ID とバージョンを含むビューモデルを受け取るようになりました。これらのフィールドをドメイン エンティティに挿入し、リポジトリに保存させます (エンティティをリロードしません)。

User = this._UserRepository.Update(user);

StaleObjectException例外が発生した場合は、他の誰かが DB 行を更新したことを意味し、ユーザーにフィードバックを提供します。

4

2 に答える 2

4

期待どおりに動作させるには、マッピングで属性SaveOrUpdateを明示的に指定する必要があります。たとえば、次のようになります。unsaved-value<id>

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

次に、とはSaveOrUpdate異なる値に割り当てられた Id プロパティを持つモデルで呼び出しを発行し、代わりに に移動します。したがって、あなたの質問に答えるために、いいえ、手動でbeforeを発行する必要はありません。舞台裏でこれを行う必要があります。0UPDATEINSERTSELECTUPDATESaveOrUpdate

于 2011-01-26T12:53:11.913 に答える
0

すでにIDを持っているので、これが更新であることがわかっているので、のsession.Update代わりにを使用してSaveOrUpdateください。

于 2011-01-26T14:51:33.590 に答える