1

NHibernate をリポジトリ デザイン パターンと組み合わせて使用​​しています。現在のタスクでは、エンティティを更新し、同じトランザクション内の別のエンティティも削除する必要があります。私はレイターで宣言ISession.BeginTransaction()し、次のようRepository's Servicesに渡しRepository's methodます:

public class SomeEntity
{
    //entity's properties
}

public class EntityRepository : IEntityRepository
{
    public void update(ISession session, Entity entity)
    {
        session.Update(entity);
    }

    public void delete(ISession session, Entity entity)
    {
        session.Delete(entity);
    }
}

public class EntityService
{
    private IEntityRepository repository;

    public EntityService(IEntityRepository repository)
    {
        //I'm using Ninject for DI here
        this.repository = repository;
    }

    public void DoTask(Entity _updateEntity, Entity _deleteEntity)
    { 
        ISession session = NHibernateHelper.OpenSession();
        using(ITransaction transaction = session.BeginTransaction())
        {
            this.repositoy.update(session, _updateEntity);
            this.repositoy.delete(session, _deleteEntity);

            transaction.Commit();
        }
    }
}

聞きたいことは

  1. Repository's Service layer管理するISessionだけでなく、ITransactionそれを渡すのは良い考えAssociate Repositoryですか?
  2. Repository's Service layerそれが良い考えではない場合、同じトランザクションでそれらのタスクを実行するために、そのトランザクションについて知らせずRepository layerにできるだけ軽量にするために、どのように設計を変更すればよいでしょうか?

編集

明確にするために、 myEntityServiceは実行business logic layerに依存するものであり、結果を(私の場合はwinform)に渡します。だから、なんとかさせてしまうと、そもそも避けたいことにつながると思いました。Repositorybusiness logicpresentation layerEntityServiceISessionITransactiontight coupling

編集2

に従ってptk93、次のように設計を変更しました。

public class SomeEntity
{
    //entity's properties
}

public class EntityRepository : IEntityRepository
{
    private ISession session;

    private ITrasaction trasaction;

    public EntityRepository()
    {
        this.session = NHibernateHelper.OpenSession();
    }

    public void BeginTransaction()
    {
        if(this.transaction != null && this.transaciont.isActive)
        {
            throw new Exception();
        }

        this.transaction = this.session.BeginTransaction();
    }

    public void CommitTransaction()
    {
        if(this.transaction == null || this.transaction.isActive = false)
        {
            throw new Exception();
        }

        this.transaction.Commit();
        this.transaction.Dispose();
    }

    public void update(ISession session, Entity entity)
    {
        if(this.transaction == null || this.transaction.isActive = false)
        {
            throw new Exception();
        }

        session.Update(entity);
    }

    public void delete(ISession session, Entity entity)
    {
        if(this.transaction == null || this.transaction.isActive = false)
        {
            throw new Exception();
        }

        session.Delete(entity);
    }
}

public class EntityService
{
    private IEntityRepository repository;

    public EntityService(IEntityRepository repository)
    {
        //I'm using Ninject for DI here
        this.repository = repository;
    }

    public void DoTask(Entity _updateEntity, Entity _deleteEntity)
    { 
        this.repository.BeginTransaction()

        this.repositoy.update(session, _updateEntity);
        this.repositoy.delete(session, _deleteEntity);

        this.repository.CommitTransaction();            
    }
}

この設計はデカップリングRepositoryに十分Repository Serviceですか?

4

2 に答える 2

1

サービスを境界サービスと制御サービスに分けることができます。境界はクライアント、Web ページなどに表示され、コントロールは境界サービスにのみ表示されます。リポジトリはクライアントに表示されていますか? あなたのユースケースでは、リポジトリはクライアント自体ではなく他のサービスによってのみ使用されるようです。したがって、それらはコントロールです。コントロールは MANDATORY でマークする必要があります。これにより、トランザクションが startend されていない状態で呼び出された場合に例外がスローされ、境界内のメソッドの最初から最後までトランザクションが startend である必要があります。

コントロール/リポジトリ UserRepository と AddressRepository を使用して 3 つのアドレスを持つユーザーを作成している場合、すべてが境界 RegistrationService の register メソッドの開始時に同じトランザクション startend になります。
すべての連絡先情報を削除する場合、コントロール AddressRepository および MailRepository は、異なるトランザクション境界を持つ ContactService と呼ばれる別の境界内で使用する必要があります。

このような決定はユース ケースによって異なりますが、私の意見では、Entity-Control-Boundary パターンがニーズに合う可能性があります。

于 2014-06-02T04:41:35.263 に答える