일반 리포지토리에 실질적인 이점이 있습니까? = new Province() { Country =

새 앱에 대한 일반 리포지토리를 만드는 이점에 대한 기사를 읽었습니다 ( ). 동일한 저장소를 사용하여 여러 엔티티 유형에 대해 여러 가지 작업을 한 번에 수행 할 수 있기 때문에 아이디어가 좋습니다.

IRepository repo = new EfRepository(); // Would normally pass through IOC into constructor 
var c1 = new Country() { Name = "United States", CountryCode = "US" };
var c2 = new Country() { Name = "Canada", CountryCode = "CA" };
var c3 = new Country() { Name = "Mexico", CountryCode = "MX" };
var p1 = new Province() { Country = c1, Name = "Alabama", Abbreviation = "AL" };
var p2 = new Province() { Country = c1, Name = "Alaska", Abbreviation = "AK" };
var p3 = new Province() { Country = c2, Name = "Alberta", Abbreviation = "AB" };
repo.Add<Country>(c1);
repo.Add<Country>(c2);
repo.Add<Country>(c3);
repo.Add<Province>(p1);
repo.Add<Province>(p2);
repo.Add<Province>(p3);
repo.Save();

그러나 나머지 리포지토리 구현은 Linq에 크게 의존합니다.

IQueryable<T> Query();
IList<T> Find(Expression<Func<T,bool>> predicate);
T Get(Expression<Func<T,bool>> predicate);
T First(Expression<Func<T,bool>> predicate);
//... and so on

이 리포지토리 패턴은 Entity Framework에서 훌륭하게 작동했으며 DbContext / DbSet에서 사용 가능한 메소드의 1 대 1 매핑을 거의 제공했습니다. 그러나 Entity Framework 외부의 다른 데이터 액세스 기술에 대한 Linq의 느린 채택으로 인해 DbContext와 직접 작업하는 것보다 어떤 이점이 있습니까?

PetaPoco 버전의 리포지토리 를 작성하려고 시도 했지만 PetaPoco는 Linq Expressions를 지원하지 않으므로 기본 GetAll, GetById, Add, Update, Delete 및 Save에만 사용하지 않는 한 일반 IRepository 인터페이스를 만드는 것은 거의 쓸모가 없습니다. 기본 클래스로 사용하십시오. 그런 다음 이전에 술어로 전달할 수있는 모든 “where”절을 처리하기 위해 특수한 메소드를 사용하여 특정 저장소를 작성해야합니다.

일반 리포지토리 패턴이 Entity Framework 외부에 유용한가요? 그렇지 않다면 누군가 Entity Framework와 직접 작업하는 대신 왜 전혀 사용하지 않습니까?


원본 링크에는 샘플 코드에서 사용한 패턴이 반영되어 있지 않습니다. 여기에 ( 업데이트 된 링크 )가 있습니다.



답변

Entity Framework에는 일반 리포지토리가 쓸모 없고 IMHO도 좋지 않습니다. 이미 제공 한 것 IDbSet<T>(일반 저장소 인 btw) 에는 추가 가치가 없습니다 .

이미 일반 리포지토리를 다른 데이터 액세스 기술의 구현으로 대체 할 수 있다는 주장은 이미 자체 Linq 공급자 작성이 필요할 수 있기 때문에 매우 약합니다.

메모리 내 데이터 스토리지로 모의 저장소 / 세트를 조롱하면 Linq 제공자가 다른 기능을 가진 다른 제공자로 대체되기 때문에 단순화 된 단위 테스트에 대한 두 번째 공통 주장 도 잘못 되었습니다. Linq-to-entities 제공자는 Linq 기능의 서브 세트 만 지원하며 IQueryable<T>인터페이스에서 사용 가능한 모든 메소드도 지원하지 않습니다 . 데이터 액세스 계층과 비즈니스 논리 계층간에 식 트리를 공유하면 데이터 액세스 계층이 위조되지 않습니다. 쿼리 논리를 분리해야합니다.

강력한 “일반적인”추상화를 원한다면 다른 패턴도 포함해야합니다. 이 경우 저장소에서 사용 된 데이터 액세스 계층에서 지원하는 특정 쿼리 언어로 변환 할 수있는 추상 쿼리 언어를 사용해야합니다. 이것은 사양 패턴에 의해 처리됩니다. Linq on IQueryable은 사양이지만 번역에는 공급자 또는 표현식 트리를 쿼리로 변환하는 일부 사용자 지정 방문자가 필요하지만 직접 단순화 된 버전을 정의하여 사용할 수 있습니다. 예를 들어 NHibernate는 Criteria API를 사용합니다. 여전히 가장 간단한 방법은 특정 방법으로 특정 저장소를 사용하는 것입니다. 이 방법은 쿼리 로직이 완전히 숨겨져 추상화 뒤에 분리되므로 단위 테스트에서 구현하기가 가장 간단하고 테스트하기도 쉽고 가짜도 가장 간단합니다.


답변

문제는 리포지토리 패턴이 아닙니다. 데이터를 얻는 것과 데이터를 얻는 방법을 추상화하는 것이 좋습니다.

여기서 문제는 구현입니다. 필터링에 임의의식이 작동한다고 가정하는 것이 최선입니다.

모든 객체에 대해 리포지토리 작업을 직접 수행하면 요점을 놓칠 수 있습니다. 데이터 개체가 비즈니스 개체에 직접 매핑되는 경우는 거의 없습니다. 이러한 상황에서 필터로 T를 전달하면 의미가 떨어집니다. 그리고 많은 기능을 제공하면 다른 공급자가 등장하면 모든 기능을 지원할 수 없습니다.


답변

일반 데이터 계층 (저장소는 특정 유형의 데이터 계층)의 값으로 인해 코드가 호출 코드에 거의 또는 전혀 영향을 미치지 않으면 서 기본 스토리지 메커니즘을 변경할 수 있습니다.

이론적으로 이것은 잘 작동합니다. 실제로, 관찰 한 바와 같이 추상화가 종종 누출됩니다. 하나의 데이터에 액세스하는 데 사용되는 메커니즘은 다른 메커니즘과 다릅니다. 경우에 따라 비즈니스 계층에 한 번 코드를 작성하고 데이터 계층에 코드를 반복하는 경우가 있습니다.

일반 데이터 계층을 생성하는 가장 효과적인 방법은 응용 프로그램에서 미리 사용할 다양한 유형의 데이터 소스를 아는 것입니다. 보시다시피, LINQ 또는 SQL이 보편적이라고 가정하면 문제가 될 수 있습니다. 새로운 데이터 저장소를 개조하려고하면 재 작성이 발생할 수 있습니다.

[편집 : 다음을 추가했습니다.]

또한 데이터 계층에서 응용 프로그램에 필요한 사항에 따라 다릅니다. 응용 프로그램이 객체를로드하거나 저장하는 경우 데이터 계층은 매우 간단 할 수 있습니다. 검색, 정렬 및 필터링의 필요성이 증가함에 따라 데이터 계층의 복잡성이 증가하고 추상화가 유출되기 시작합니다 (예 : 질문에 LINQ 쿼리 노출). 그러나 사용자가 고유 한 쿼리를 제공 할 수있게되면 데이터 계층의 비용 / 혜택을 신중하게 평가해야합니다.


답변

거의 모든 경우 데이터베이스 위에 코드 계층을 갖는 것이 좋습니다. 일반적으로 위 코드에서 “GetByXXXXX”패턴을 선호합니다. UI를 데이터 인터페이스가 복잡하게 유지하면서 필요에 따라 쿼리를 최적화 할 수 있습니다.

제네릭을 이용하는 것은 확실히 공정한 게임 Load<T>(int id)입니다. 그러나 LINQ를 중심으로 리포지토리를 구축하는 것은 2010 년에 약간의 추가 된 유형 안전성으로 SQL 쿼리를 삭제하는 것과 같습니다.


답변

글쎄, 제공된 링크를 통해 그것이 편리한 래퍼 일 수는 DataServiceContext있지만 코드 조작을 줄이거 나 가독성을 향상 시키지는 않습니다. 또한에 대한 액세스 DataServiceQuery<T>가 차단되어 유연성이 .Where()및로 제한됩니다 .Single(). 도 있습니다 AddRange()또는 대체를 제공합니다. Delete(Predicate)유용 할 수있는 것도 제공되지 않습니다 (Joes repo.Delete<Person>( p => p.Name=="Joe" );삭제). 기타.

결론 : 이러한 API는 기본 API를 방해하고 몇 가지 간단한 작업으로 제한합니다.


답변

나는 “예”라고 말할 것입니다. 데이터 모델에 따라, 잘 개발 된 Generic Repository는 데이터 액세스 계층을 더 얇고 깔끔하며 훨씬 강력하게 만들 수 있습니다.

이 기사 시리즈를 읽으십시오 ( @ chris-pratt ) :