2

필자는 Active Directory와 SQL 데이터베이스에 지속성으로 액세스해야하는 DDD 기반 시스템을 구축하는 고유 한 상황이 있습니다.여러 데이터 저장소를 처리 할 때 저장소 패턴과 작업 단위를 어떻게 구현합니까?

public interface IUnitOfWork 
{ 
    void BeginTransaction() 
    void Commit() 
} 

우리의 저장소는 다음과 같이 보았다 : 처음에이 우리의 디자인은 우리가이처럼 보였다 작업 단위 있었다 설정했기 때문에 문제가 않네이 설정에서

public interface IRepository<T> 
{ 
    T GetByID() 
    void Save(T entity) 
    void Delete(T entity) 
} 

을 우리의 부하 및 저장 우리가 직접 작성했기 때문에 두 데이터 저장소 간의 매핑을 처리합니다. 작업 단위 (UOW)는 트랜잭션을 처리하고 리파지토리가 지속성을 위해 사용할 Linq To SQL 데이터 컨텍스트를 포함합니다. 활성 디렉터리 부분은 인프라에서 구현되고 각 Save() 메서드의 저장소에서 사용되는 도메인 서비스에 의해 처리되었습니다. Save()는 데이터 컨텍스트와 상호 작용하여 모든 데이터베이스 작업을 담당했습니다.

이제 엔티티 프레임 워크에 적용하여 POCO를 활용하려고합니다. 이상적으로는 도메인 객체가 객체 컨텍스트에 의해 추적되기 때문에 Save() 메서드가 필요하지 않으며 객체 컨텍스트에서 변경 사항을 저장하도록 작업 단위에 Save() 메서드를 추가하면됩니다. 새 객체를 컨텍스트에 등록합니다.

public interface IUnitOfWork 
{ 
    void BeginTransaction() 
    void Save() 
    void Commit() 
} 

public interface IRepository<T> 
{ 
    T GetByID() 
    void Add(T entity) 
    void Delete(T entity) 
} 

이 엔티티 프레임 워크 데이터 액세스 문제를 해결하지만, 우리의 Active Directory 통합 문제가 해결되지 않습니다 : 새로운 제안 된 디자인은 더 다음과 같습니다. 전에는 저장소의 Save() 메소드에 있었지만 이제는 집이 없습니다. 작업 단위 (UOW)는 엔티티 프레임 워크 데이터 컨텍스트 이외의 것을 아는 것이 아닙니다. 이 논리는 어디에서 가야합니까? 필자는 엔티티 프레임 워크를 사용하는 데이터 저장소가 하나 뿐인 경우에만이 디자인이 작동한다고 주장합니다. 이 아이디어에 가장 잘 접근하는 방법은 무엇입니까? 이 논리는 어디에 두어야합니까?

답변

4

나는 이것을 올린 이래로 내가 배운 것을 되돌아보고 후속 조치를 원했다. 리포지토리 패턴을 그대로 유지하려고한다면 문제가되지 않는 데이터 저장소가있는 것 같습니다. 두 개의 데이터 저장소가있는 경우 둘 다 동일한 저장소에 씁니다. 중요한 것은 저장소 패턴이 나타내는 외관을 유지하는 것입니다. 메모리 컬렉션. 저에게 진실한 추상화 같이 느끼지 않기 때문에 나는 분리되는 보관소를하지 않을 것입니다. 후드 아래에있는 기술로 인해 그 시점의 설계가 결정됩니다. dddstepbystep.com에서 인용하십시오 :

리포지토리 뒤에는 무엇이 있습니까? 꽤 당신이 좋아하는 무엇이든. 네, 라고 들었습니다. 데이터베이스가 있거나 많은 다른 데이터베이스를 가질 수 있습니다. 관계형 데이터베이스 또는 개체 데이터베이스를 사용할 수 있습니다. 에는 메모리 데이터베이스가 있거나 메모리 항목이 인 목록을 포함하는 싱글 톤이있을 수 있습니다. REST 레이어 또는 SOA 서비스 세트 또는 파일 시스템 또는 메모리 캐시를 가질 수 있습니다. 의 제한 사항은 리포지토리가 다음과 같이 작동 할 수 있어야합니다. 컬렉션을 도메인에 추가하십시오. 이 유연성은 저장소와 기존 데이터 액세스 기술 간의 주요 차이점입니다 ( ).

http://thinkddd.com/assets/2/Domain_Driven_Design_-_Step_by_Step.pdf

0

IMO 클래스의 서비스 유형에서 이러한 repos에 대한 호출을 모두 래핑합니다. 그런 다음 IoC/DI를 사용하여 repo 유형을 서비스 클래스에 주입합니다. 당신은 엔트리에 대해 2 repos, 1을 가질 것입니다. 프레임 워크와 광고를 지원하는 1. 이렇게하면 각 리포는 기본 데이터 저장소 만 취급하므로 교차 할 필요가 없습니다.

여러 작업 단위를 지원하기 위해 수행 한 작업은 IUnitOfWork를 더 많은 공장으로 유지하는 것입니다. IUnitOfWorkScope라는 또 다른 유형은 실제 작업 단위이며 커밋 메소드 만 가지고 있습니다.

namespace Framework.Persistance.UnitOfWork 
{ 
    public interface IUnitOfWork 
    { 
     IUnitOfWorkScope Get(); 

     IUnitOfWorkScope Get(bool shared); 
    } 

    public interface IUnitOfWorkScope : IDisposable 
{ 
    void Commit(); 
} 
} 

이렇게하면 작업 단위의 다른 구현을 서비스에 삽입하여 이들을 나란히 사용할 수 있습니다.

1

먼저 IoC 컨테이너를 사용하고 있다고 가정합니다. 나는 당신이 각 엔티티 유형에 대해 진정한 리포지토리를 만들 것을 주창합니다. 이것은 당신이 뭔가를 구현하는 클래스의 각 개체 컨텍스트 EntitySet 포장 의미 :

interface IRepository<TEntity> { 
    TEntity Get(int id); 
    void Add(TEntity entity); 
    void Save(TEntity entity); 
    void Remove(TEntity entity); 
    bool CanPersist<T>(T entity); 
} 

CanPersist 단지 그 저장소 인스턴스가 전달 된 개체를 지속 지원하는지 여부를 반환하고 UnitOfWork.Save 아래에 설명에 의해 다형 적으로 사용된다.

각 IRepository에는 IRepository를 "트랜잭션"모드로 구성 할 수있는 생성자도 있습니다.그래서, EF, 우리는이있을 수 있습니다

public partial EFEntityARepository : IRepository<EntityA> { 
    public EFEntityARepository(EFContext context, bool transactional) { 
    _context = context; 
    _transactional = transactional; 
    } 
    public void Add(EntityA entity) { 
    _context.EntityAs.Add(entity); 
    if (!_transactional) _context.SaveChanges(); 
    } 
} 

의 UnitOfWork는 다음과 같아야합니다

interface UnitOfWork { 
    void Add(TEntity entity); 
    void Save(TEntity entity); 
    void Remove(TEntity entity); 
    void Complete(); 
} 

의 UnitOfWork 구현은 모든 IRepository의 인스턴스를 얻기 위해 의존성 주입을 사용합니다. UnitOfWork.Save/Add/Remove에서 UoW는 각 IRepository의 CanPerist에 인수 엔터티를 전달합니다. true 반환 값의 경우 UnitOfWork는 해당 엔티티를 해당 IRepository 및 의도 한 작업에 고유 한 개인 모음에 저장합니다. Complete에서 UnitOfWork는 모든 개인 개체 컬렉션을 살펴보고 각 개체에 대한 적절한 IRepository에서 적절한 작업을 호출합니다.

부분적으로 EF에 의해 유지되어야하고 부분적으로 AD에 의해 유지되어야하는 엔티티가있는 경우 해당 엔티티 유형에 대해 두 개의 IRepository 클래스를 갖게됩니다 (해당 엔티티 유형의 인스턴스를 전달할 때 둘 다 CanPersist에서 true를 반환합니다) .

EF와 AD 사이의 원 자성을 유지하는 것은 별개의 중요한 문제입니다.