2010-11-24 4 views
15

다음 구현을 가지고 있으며 세션과 트랜잭션을 위해 NHibernate를 올바르게 사용하는지에 대한 피드백이 필요합니다. 내 이전 구현에서NHibernate 작업 단위 패턴과 Ninject의 올바른 사용

public class Repository : IRepository 
{ 
    private readonly ISessionFactory _sessionFactory; 

    public Repository(ISessionFactory sessionFactory) 
    { 
     _sessionFactory = sessionFactory; 
    } 

    public void Add(IObj obj) 
    { 
     using (var unitOfWork = new UnitOfWork(_sessionFactory)) 
     { 
      unitOfWork.CurrentSession.Save(obj); 
      unitOfWork.Commit(); 
     }   
    } 
} 

내가 그렇게

public Repository(IUnitOfWork unitOfWork) 
    {... 
처럼 내 저장소 생성자에 IUnitOfWork를 주입 것 :

public interface IUnitOfWork : IDisposable 
{ 
    ISession CurrentSession { get; } 
    void Commit(); 
    void Rollback(); 
} 

public class UnitOfWork : IUnitOfWork 
{ 
    private readonly ISessionFactory _sessionFactory; 
    private readonly ITransaction _transaction; 

    public UnitOfWork(ISessionFactory sessionFactory) 
    { 
     _sessionFactory = sessionFactory; 
     CurrentSession = _sessionFactory.OpenSession(); 
     _transaction = CurrentSession.BeginTransaction(); 
    } 

    public ISession CurrentSession { get; private set; } 

    public void Dispose() 
    { 
     CurrentSession.Close(); 
     CurrentSession = null; 
    } 

    public void Commit() 
    { 
     _transaction.Commit(); 
    } 

    public void Rollback() 
    { 
     if (_transaction.IsActive) _transaction.Rollback(); 
    } 
} 

Ninject에 여기

Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope(); 
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope(); 
Bind<IRepository>().To<Repository>().InTransientScope(); 

를 결합하는 것은 사용의 예입니다

그러나 Dispose() 메서드가 실행되어 후속 호출에서이 예외를 throw하면 "폐기 된 개체에 액세스 할 수 없습니다. 객체 이름 : 'AdoTransaction'. "

+3

귀하의 최종 결정은 확실하지 않지만 그것을하지 마십시오! :) 진지하게, NHibernate는 이미 많은 추상화와 UoW 패턴을 추가한다. 그냥 상자 밖으로 똑바로 NHibernate를 사용하여 코드를 간단하게 유지. 디버깅을 위해 더 많은 추상화를 원하십니까? –

답변

35

첫 번째 관찰 : 저장소가 작업 단위를 커밋하지 않아야합니다. 이렇게하면 작업 단위 패턴 전체가 무효화됩니다. 변경 사항을 저장소에 즉시 저장하면" 마이크로 관리 "NHibernate 세션

작업 단위는 응용 프로그램/서비스 계층에서 스택 위로 올라와야합니다. 이렇게하면 잠재적으로 다른 저장소에서 여러 작업을 수행하는 응용 프로그램 코드를 가질 수 있습니다. 끝은 모든 것을 한꺼번에 끝냅니다.

UnitOfWork 클래스 자체는 실제로 보이는지는 모르지만 스스로 확인해야합니다 .Hibernate에서 ISessi 에 귀하의 작업 단위입니다. UnitOfWork 클래스가 많은 가치를 추가하지 못하는 것 같습니다 (특히 CurrentSession 속성을 노출하고 있기 때문에 특히 그렇습니다).

하지만 평생 동안 생각해야합니다. 나는 당신이이 시점에서 잘못 생각한 것 같습니다. 세션 수명 관리는 개발중인 애플리케이션의 유형에 따라 달라집니다. 웹 앱에서 일반적으로 요청 당 작업 단위가 필요합니다 (요청 당 nhibernate 세션에 대해 Google을 원할 수 있습니다). 데스크톱 애플리케이션에서는 약간 더 복잡해지기 때문에 대부분의 경우 '화면 당 세션'또는 '비즈니스 트랜잭션 당 대화'를 원하게됩니다.

+0

피드백 Jeroenh에게 감사드립니다. 우리의 응용 프로그램은 단순한 crud 작업 만 수행하면되며 여러 작업을 수행 할 필요가 없으며 모든 것을 한 번에 완료 할 수 있습니다. 내가 Unitession에 대해 직접 작업하지 않기로 선택한 이유는 UnitOfWork가 전환 세션을 추상화하고 전환을 시작하고 세션을 종료하기를 원했기 때문입니다. –

+6

IUnitOfWork의 이점은 ORM에 대한 결합이 감소 된 것입니다. 또는 적어도 내가 생각할 수있는 유일한 이점은 다음과 같습니다. –

+5

@ Ryan Barett하지만 그 용도는 무엇입니까? http://ayende.com/Blog/archive/2010/07/30/the-false-myth-of-encapsulating-data-access-in-the-dal.aspx – jeroenh

8

대부분 CRUD 유형의 애플리케이션이 있으며 리포지토리 패턴으로 작업 단위를 구현했지만 실제로 세션/트랜잭션 분할에서 벗어날 수는 없습니다. 세션과 거래에는 다른 평생이 필요합니다. 데스크톱 환경에서 세션은 대개 "화면 단위"이고 트랜잭션은 "사용자 별 작업"입니다.

자세한 내용은 excellent article입니다. 내가 함께 결국 그래서

했다 : -> 랩 세션, IDisposable

  • IAtomicUnitOfWork를 구현 -

    • IUnitOfWork>는 거래를 랩 구현 IDisposable
    • IRepository -> 제공 가져 오기, 저장, 삭제 검색어 액세스

    을 빌드하려면 IAtomicUnitOfWork을 만들고 IRepository을 빌드하려면 IAtomicUnitOfWork이 필요하므로 올바른 트랜잭션 관리가 수행됩니다.그게 내 자신의 인터페이스를 구현하여 얻은 전부입니다.

    jeroenh이 말한 것처럼 ISessionITransaction을 사용하는 것이 거의 비슷하지만 결국에는 내가 정의한 인터페이스에 대해 모든 코드를 작성하는 것이 조금 더 편하다고 느꼈습니다.

  • +0

    IUoW를 IRepository로 보내는 좋은 아이디어. 개념적 분열 : IUoW는 정의상 트랜잭션입니다. 세션의 개념은 조금 다르다. 다른 이름을 사용하려면 그 추상화가 달라야한다. (나는 IDatabaseGenericSession이라고 부른다.) –

    +0

    @Ryan Barrett : 네, 세션 랩퍼의 더 나은 이름은 "컨텍스트 ". ObjectContext 이미 .NET에서 찍은 것 같아요, 안 그래? 어쩌면 EntityContext? –

    3

    응답의 중요한 부분은 트랜잭션 크기를 원하는 것입니다. 지금 당장 (jeroenh이 지적했듯이) 트랜잭션은 저장소에 대한 메소드 호출 당입니다. 이것은 매우 작아서 아마도 필요하지 않을 것입니다. ASP.MVC 응용 프로그램을 만들었고 단일 HTTP 요청의 모든 내용을 포함하는 트랜잭션 크기를 사용합니다. 여러 데이터베이스 읽기/업데이트 일 수 있습니다. 나는 IOC를 위해 같은 작업 단위와 Ninject를 사용하고 있습니다. 어쩌면 무언가가 당신의 문제에 도움이 될 것 봐 :이 도움이

    http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/

    http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

    http://bobcravens.com/2010/09/the-repository-pattern-part-2/

    http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/

    희망을.

    +0

    Bob에게 감사드립니다. 내 응용 프로그램이 MVC 응용 프로그램이 아니지만 아이디어는 같습니다. –

    +0

    안녕하세요 밥, 불행히도 귀하의 블로그는 blog.bobcravens.com에서 bobcravens.com으로 URL이 변경되었습니다. 따라서 예를 들어 이미지 링크와 같이 많은 부분이 손상되었습니다. 희망을 고칠 수 있기를 바랍니다. –

    관련 문제