일반 리포지토리 EF 4.1의 요점


145

DbContext, DbSet 및 관련 인터페이스에 대해 자세히 살펴보면 왜 이러한 구현에 대해 별도의 "일반"리포지토리를 구현해야하는지 궁금합니다.

DbContext 및 IDbSet은 필요한 모든 작업을 수행하고 DbContext 내에 "작업 단위"를 포함하는 것처럼 보입니다.

여기에 무언가가 없거나 사람들이 아무런 이유없이 다른 의존성 계층을 추가하는 것을 좋아하는 것 같습니다.


이것은 약간의 논쟁 / 의견에 근거한 문제입니다. 나는 여기서 이것을 논의 했다 .
Joshi를

답변:


202

당신은 실제로 옳습니다. DbContext작업 단위 패턴 IDbSet의 구현이며 저장소 패턴의 구현입니다.

리포지토리는 현재 매우 인기가 있고 과도하게 사용되고 있습니다. 엔터티 프레임 워크를위한 리포지토리 생성에 관한 수십 개의 기사가 있기 때문에 모든 사람이이를 사용하지만 실제로이 결정과 관련된 문제를 설명하는 사람은 없습니다.

저장소를 사용하는 주요 이유는 일반적으로 다음과 같습니다.

  • 상위 레이어에서 EF 숨기기
  • 더 나은 코드 테스트 가능

첫 번째 이유는 일종의 건축 학적 순도 및 EF와 독립적으로 상위 계층을 만들면 나중에 다른 지속성 프레임 워크로 전환 할 수 있다는 좋은 아이디어입니다. 현실 세계에서 몇 번이나 그런 것을 보았습니까? 이러한 이유 때문에 리포지토리에는 기본적으로 EF에서 허용하는 기능을 래핑하는 많은 추가 기능이 노출되어야하므로 EF 작업이 훨씬 어려워집니다.

이와 동시에 EF 코드를 래핑하면 코드를보다 체계적으로 정리하고 분리 규칙을 따를 수 있습니다. 저에게 이것은 저장소와 작업 단위의 유일한 장점 일 수 있지만 EF를 사용하여이 규칙을 따르면 코드를 더 잘 유지 관리하고 읽을 수있게 만들 수 있지만 초기 노력으로 응용 프로그램을 만드는 데 훨씬 더 많은 노력이 필요하다는 것을 이해해야합니다 작은 응용 프로그램의 경우 이것은 복잡하지 않을 수 있습니다.

두 번째 이유는 부분적으로 맞습니다. EF의 가장 큰 단점은 조롱하기 어려운 견고한 아키텍처이므로 상위 계층을 단위 테스트하려면 구현을 조롱 할 수 있도록 EF를 어떻게 든 래핑해야합니다. 그러나 이것은 내가 여기에 설명한 다른 많은 결과를 가지고 있습니다 .

Ayende의 블로그를 따릅니다 . NHibernate를 사용한 적이 있다면 아마도 그의 기사를 알고있을 것입니다. 이 사람은 최근 NHibernate와 함께 저장소를 사용하는 것에 대해 여러 기사를 썼지 만 NHibernate는 훨씬 더 조롱 할 수 있습니다.


3
IDbSet파생 된 컨텍스트에서 사용자 정의 인터페이스를 정의 할 수도 있지만 그 전부를 조롱 할 수 있습니다. 코드에서 ChangeTracker, 항목 또는 다른 항목을 사용하면 모든 항목을 포장하는 데 큰 노력이 필요합니다.
Ladislav Mrnka

1
예 EF는 성능 중심 도구가 아닙니다. 최소한 MS는 향후 버전에서이를 개선 할 수있는 많은 기회가 있습니다.
Ladislav Mrnka

2
@chiccodoro : 그렇습니다. 그러나 조롱 된 클래스 가 Linq-to-entities 쿼리에 내부적으로 적용되는 매개 변수로 노출 IQueryable되거나 수락 Expression<>되면 단위 테스트로 테스트 할 수없는 부작용으로 조롱 된 구성 요소 외부의 논리를 정의합니다.
Ladislav Mrnka

8
DbSet 및 BdContext를 비즈니스 계층에서 바로 사용하는 경우 DataLayer 프로젝트뿐만 아니라 EntityFramework.dll을 참조해야합니다. 그것만으로도 일종의 포장이 필요하다는 것을 알 수 있습니다.
Ingó Vals

2
downvote : 불완전-저장소 인터페이스 뒤의 EF를 추상화하면 SL과 WPF에서 모두 동일한 클라이언트 코드를 실행할 수 있습니다.
h.alex

21

나는 같은 문제로 어려움을 겪고 있으며 EF 레이어의 단위 테스트를위한 모형이 중요합니다. 그러나 파생 된 DbContext가 일반 인터페이스를 구현하고 DbSet 대신 IDbSet을 노출시켜 EF 4.1 DbContext를 조롱 할 수 있도록 설정하는 방법을 설명하는이 위대한 기사를 살펴 보았습니다. 데이터베이스 우선 접근 방식을 사용하고 있기 때문에 데이터베이스가 이미 존재하기 때문에 파생 된 DbContext를 생성하는 데 사용되는 T4 템플릿을 수정하여 IDbSet 인터페이스를 반환하고 일반 인터페이스에서 파생했습니다. 이렇게하면 전체 내용을 쉽게 조롱 할 수 있으며 고유 한 작업 단위 (UOW) 또는 저장소 패턴을 구현할 필요가 없습니다. 일반 인터페이스를 사용하기 위해 서비스 코드를 작성하고 단위 테스트를 진행할 때

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/


5

저장소를 작성하는 한 가지 이유는 EntityFramework에서 다른 것으로 또는 그 반대로 이동하기로 결정한 경우 DBSet 및 DbContext의 구현을 숨길 수 있기 때문입니다.

예를 들어 NHibernate를 사용하고 있었고 저장소 프레임 워크 내에서 해당 프레임 워크에 대한 모든 호출을 래핑했습니다. 그들은 "일반적인"것으로 IEnumerable을 반환하고 내 저장소에는 표준 CRUD 작업 (업데이트, 삭제 등)이 있습니다. 나는 오랫동안 Entity Framework로 옮겼습니다. 그렇게 할 때 ViewModel 클래스에서 또는 저장소를 가리 키기 때문에 그 이상을 변경할 필요가 없었습니다. 내 저장소의 내부 만 변경하면됩니다. 이것은 이주 할 때 삶을 훨씬 쉽게 만들었습니다.

(ISeries에 연결하고 있기 때문에 NHibernate를 사용했으며 당시에는 IF와 함께 EF를 사용한 비용 효과적인 구현이 없었습니다. 사용 가능한 유일한 것은 DB2Connect를 위해 IBM에 $ 12,000를 지불하는 것이 었습니다)


"거의"(DBSet 및 DbContext를 숨기는 주제에서) EF를 소비자에게 노출 할 필요는 없지만 (예 : DI를 활용하는 경우) IDbSet <T> 속성을 ​​노출하는 인터페이스가 필요합니다. 한 단계 더 나아가서 대신 모든 속성을 IQueryable <T> 's로 입력하십시오. 그러나 요점은 DbSet 및 DbContext에 대한 의존성을 완전히 숨길 수 있다는 것입니다. 그런 다음 CRUD op를 확장 방법으로 작성할 수 있으며, 다른 백업 저장소에 대해 여러 확장 방법을 작성할 수 있습니다. 그러나 LINQ 사용을 숨기지 않을 것입니다.
숀 윌슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.