문제

다음 코드와 같은 작업 단위 패턴을 보았습니다.

    private HashSet<object> _newEntities = new HashSet<object>();
    private HashSet<object> _updatedEntities = new HashSet<object>();
    private HashSet<object> _deletedEntities = new HashSet<object>();

그런 다음 각 해시 세트에 엔티티를 추가하는 방법이 있습니다.

Commit Unitofwork에서 각 엔티티에 대한 일부 매퍼 인스턴스를 생성하고 삽입, 업데이트, 일부 가상의 맵퍼에서 메소드를 삭제합니다.

이 접근법의 문제는 다음과 같습니다. 인서트, 업데이트, 삭제 방법의 이름은 하드 코딩되어 있으므로 단순한 단위 작업이 간단한 CRUD 작업을 수행 할 수있는 것 같습니다. 그러나 다음과 같은 사용이 필요하다면 어떻게해야합니까?

UnitOfWork ouw = new UnitOfWork();
uow.Start();

ARepository arep = new ARepository();
BRepository brep = new BRepository(); 

arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere();

uow.Commit();

이제 삽입, 업데이트, 작업을 위해 A와 B 엔티티 만 등록 할 수 있기 때문에 3 개의 해시 세트 접근 방식이 실패하지만 지금 해당 사용자 정의 작업이 필요합니다.

그래서 내가 할 수없는 것 같습니다 언제나 저장소 작업을 쌓은 다음 모두 수행합니다. UnitOfWork.Commit();

이 문제를 해결하는 방법? 첫 번째 아이디어는 - 방법의 주소를 저장할 수 있다는 것입니다.

arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere(); 

UOW 인스턴스에서 실행하십시오 uow.Commit() 그러나 모든 메소드 매개 변수도 저장해야합니다. 그것은 복잡하게 들립니다.

다른 아이디어는 리포지토리를 완전히 인식하는 것입니다. DoSomeNonSimpleUpdateHere 나는 UOW 달리기가 있음을 감지 할 수 있고 나는 수행하지 않습니다. DoSomeNonSimpleUpdateHere 그러나 저장소 인스턴스의 일부 스택에 작동 매개 변수와 '보류중인'상태를 저장합니다 (UOW가 구체적인 저장소 구현에 의존해서는 안되기 때문에 UOW에 모든 것을 저장할 수는 없습니다). 그런 다음 UOW 인스턴스에 관련 저장소를 등록합니다. UOW가 전화 할 때 Commit, 트랜잭션을 열고 보류중인 각 저장소에 대해 Flush ()와 같은 것을 호출합니다. 이제 모든 저장소 방법에는 UOW 감지 및 작업 연기를위한 몇 가지 사항이 필요합니다. Commit().

짧은 질문은 - UOW의 여러 리포지토리에 보류중인 모든 변경 사항을 등록하는 가장 쉬운 방법은 무엇입니까? Commit() 모두 단일 거래에서?

도움이 되었습니까?

해결책

복잡한 업데이트조차도 하나 이상의 도메인 주체에 대한 일련의 수정으로 나눌 수있는 것 같습니다. DosomenonsimpleUpdateHere () 호출은 여러 다른 도메인 주체를 수정할 수 있으며, 이는 각 객체에 대해 itonofwork.registerdirty (domainobject)로 해당 호출을 트리거 할 수 있습니다. 아래 샘플 코드에서 호출을 dosomenonsimpleupdatehere로 대체하여 시스템에서 비활성 사용자를 제거하는 코드로 대체했습니다.

UnitOfWork uow = GetSession().GetUnitOfWork();
uow.Start();

UserRepository repository = new UserRespository();
UserList users = repository.GetAllUsers();

foreach (User user in users)
{
  if (!user.IsActive())
    users.Remove( user );
}

uow.Commit();

모든 사용자를 반복 해야하는 것에 대해 우려하는 경우, 다음은 기준 객체를 사용하여 데이터베이스에서 가져온 사용자 수를 제한하는 대체 접근 방식이 있습니다.

UnitOfWork uow = GetSession().GetUnitOfWork();
uow.Start();

Repository repository = new UserRespository();
Criteria inactiveUsersCriteria = new Criteria();
inactiveUsersCriteria.equal( User.ACTIVATED, 0 );
UserList inactiveUsers = repository.GetMatching( inactiveUsersCriteria );
inactiveUsers.RemoveAll();

uow.Commit();

userList.remove 및 userList.Removeall 메소드는 제거 된 각 사용자의 단위로 통지합니다. Unitofwork.commit () 호출되면 _deletedentities에서 찾은 각 사용자를 삭제합니다. 이 접근법을 사용하면 각 특수 사례에 대해 SQL 쿼리를 작성하지 않고도 임의로 복잡한 코드를 만들 수 있습니다. 단위로 워크가 모든 비활성 사용자에 대해 하나의 명령문 대신 다중 삭제 명령문을 실행해야하므로 배치 업데이트를 사용하는 것이 유용합니다.

다른 팁

이 문제가 있다는 사실은 저장소 패턴을 사용하지 않고 다중 테이블 데이터 게이트웨이와 비슷한 것을 암시합니다. 일반적으로 저장소는 집계 루트를로드하고 저장하기위한 것입니다. 따라서 엔티티를 저장하면 지속성 계층이 해당 집계 루트 엔티티 인스턴스의 객체 그래프의 모든 변경 사항을 저장합니다.

코드에 한 테이블 (또는 엔터티) 당 대략 하나의 "리포지토리"가있는 경우 실제로 테이블 데이터 게이트웨이 또는 데이터 전송 객체를 사용하는 것일 수 있습니다. 이 경우 각 Save () 메소드에서 활성 트랜잭션 (또는 작업 단위)을 참조 할 수있는 수단이 필요할 수 있습니다.

Evans DDD Book에서 그는 저장소의 클라이언트에게 트랜잭션 제어를 남겨 두는 것이 좋습니다. 실제로 테이블 데이터 게이트웨이 패턴을 사용하는 경우 피하기가 더 어려울 수는 있지만 모범 사례가 아니라는 데 동의합니다.

나는 마침내 이것을 발견했다 :

http://www.goeleven.com/blog/82

저자는 업데이트/삽입/삭제를 위해 세 개의 목록을 사용하여 문제를 해결하지만 엔티티를 저장하지는 않습니다. 대신 저장소 대의원과 그 매개 변수가 저장됩니다. 따라서 커밋시 저자는 등록 된 각 대의원에게 전화하십시오. 이 접근법을 사용하면 복잡한 저장소 방법을 등록 할 수 있으며 별도의 abtedatagateway를 사용하지 마십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top