0

いくつかのプレゼンテーション レイヤー (Web、モバイル、wpf、wcf、バックグラウンドで動作する Windows サービスなど) を持つアプリケーションがあり、NHibernate を使用してドメイン オブジェクトを保持しています。データを永続化するためのリポジトリ (クラス ライブラリ) と、これらのリポジトリを使用してビジネス ルールに従って永続化するためのサービス レイヤーがあります。私の質問は、このサービス層でトランザクション管理を実装する方法がわからないということです。おそらく、同じサービス レイヤー メソッドで (複数の) リポジトリを使用し、サービス レイヤーでトランザクションを制御する必要があります。私はこのようなものを(属性によって)実装したいと思います:

public class DomainObjectService
{
   [Transactional]
   public bool CreateDomainObject(DomainObject domainObject, /* other parameters */)
   { 
       foreach(var item in /* collection */)
       {
           _itemRepository.Save(item);
       }

       if (/* some condition */) {
          /* change the domainObject here */
       }

       _domainObjectRepository.Save(domainObject);
   } 
}

そして、このトランザクション属性は、エラーが発生したときにコミット/ロールバックを使用して私のトランザクションを制御しますか? 出来ますか?または、これを行う別の解決策はありますか?

ありがとうございました

4

1 に答える 1

3

What you have asked does not have a straight forward answer.

The behavior you wish to have sounds like you need to implement a unit of work pattern.

NHibernate's own ISession is in fact an implementation of a unit of work. I personally recommend implementing your own unit of work so that you have greater control over what your specific application considers a unit of work.

The use of attributes in a service layer class really doesn't make a lot of sense to me personally. I have seen people create custom controller attributes in an MVC application that handles transactions but I've never personally agreed with that kind of implementation.

You mentioned using more than one repository in the service layer. This is quite a common practice but it also means that each of those repositories will need to be operating within the same unit of work. If you application is using dependency injection, then one option is to have each repository accept an ISession in its constructor. Your dependency injection framework of choice could be setup in such a way as to inject the same ISession into all of the repositories. Your setup could be configured to begin a new transaction every time a new ISession is created.

You also mentioned different presentation layers such as web, mobile, wpf, etc. How you deal with sessions and transactions in each of those different types of applications can be quite different. That is why I always point people in the unit of work direction because each of those different application types could have a completely different definition for what it considers a unit of work. For a web application, you would typically go with a new unit of work for each web request. For a wpf application, the unit of work could be per screen, or until the user hits the save button, etc. Also, by implementing a unit of work, you can reuse that same unit of work implementation more easily across those different application types.

Again, this is not a question wish a straight forward answer but in general, I typically make use of a custom unit of work and a dependency injection framework to make this problem much easier to deal with.

Here are some helpful links that you may wish to investigate:

于 2012-08-30T15:38:42.293 に答える