리포지토리 패턴을 사용하는 경우


20

최근에 ORM과 함께 저장소 패턴을 사용하는 것이 좋지 않다는 것을 읽었습니다. 내 이해에서 이것은 SQL 데이터베이스에 제공하는 추상화가 너무 누설되어 패턴에 포함되지 않기 때문입니다.

이것에 대해 몇 가지 질문이 있습니다.

  1. ORM을 끄려면 어떻게해야합니까? 저장소에 ORM 특정 코드가 없으면 응용 프로그램에 ORM 특정 코드가 있습니다.

  2. ORM을 사용하지 않고 데이터 액세스 및 오브젝트 데이터 채우기에 ADO.NET을 사용하는 경우에도 저장소 패턴이 여전히 유효합니까?

  3. ORM을 사용하지만 리포지토리 패턴은 사용하지 않는 경우 일반적으로 사용되는 쿼리를 어디에 보관합니까? 각 쿼리를 클래스로 표현하고 인스턴스를 만들기 위해 일종의 쿼리 팩토리를 갖는 것이 현명합니까?


1
1) 서로 다른 동작으로 인해 ORM을 교체 할 수는 없습니다. 둘 다 linq를 지원하더라도 응용 프로그램이 중단 될 정도로 충분히 다르게 동작합니다. 예를 들어, 지연로드 동작, 더러운 추적, 유령 프록시 등 .. .. 테스트 할 수있는에-MEM 구현을위한 ORM 스왑 아웃 할 수 있지만 좋은
로저 요한슨

가치있는 것을 위해, Repository / ORM 토론에 대한 나의 의견은 여기에있다 : stackoverflow.com/questions/13180501/…
Eric King

그것이 나쁜 습관이라는 것을 어디에서 읽었습니까?
Dave Hillier

답변:


3

1) 참,하지만 얼마나 자주 ORM을 전환합니까?
2) ORM 컨텍스트는 일종의 저장소이기 때문에 쿼리 작성, 데이터 검색, 매핑 등 많은 작업을 숨기므로 ORM을 사용하지 않는 경우 해당 논리는 여전히 어딘가에 있어야합니다. 나는 그것이 단어의 가장 엄격한 의미에서 저장소 패턴으로 자격이 될지 모르겠습니다 ...
3) 쿼리를 캡슐화하는 것이 자주 보는 것이지만 일반적으로 테스트 / 스터 빙 목적으로 더 많이 사용됩니다. 그 외에는 응용 프로그램의 여러 부분에서 쿼리를 재사용 할 때 조심해야합니다. 왜냐하면 n 시간 (n은 쿼리를 사용하는 장소의 수)을 변경할 수있는 것에 대한 종속성을 생성 할 위험이 있기 때문입니다.


1
1) 당신은 잘못된 질문을하고 있습니다. 얼마나 자주 중요하지는 않지만 한 번만 있으면됩니다. 사용 가능한 ORM 옵션의 수가 많으므로 이미 사용중인 것보다 나은 옵션이있을 수 있습니다. 이제 질문이됩니다 : 당신이 할 때 어떻게됩니까? 리포지토리는 멋진 추상화를 제공합니다. 나는 거기에 있었고 처음부터 그런 추상화를했으면 좋겠다.
devnull

3
@devnull 동의하지 않습니다. 최대 한 번 발생하면 허용 가능한 위험으로 간주합니다. 잘못된 선택을하는 것이 두려운 경우 : 한 가지를 선택하기 전에 더 많은 실험을하십시오. 이론적으로는 이러한 추상화가 좋게 들리지만 실제로 ORM의 API의 상당 부분을 다시 작성하는 것은 실제로 언젠가 다른 곳에서 다른 것을 선택할 수 있기 때문입니다. 나에게 그것은 낭비되는 노력, 여분의 코드 및 더 많은 코드를 유지하고 보증해야합니다. 또한 ORM을 전환해도 전체 응용 프로그램에 영향을 미치지 않아야합니다. 도메인 경계를 배치하는 법을 배웁니다.
Stefan Billiet

ORM 변경이 리포지토리의 유일한 이유는 아닙니다. 애플리케이션에 [분산] 캐시를 도입해야하는 경우 모든 변경 사항이 저장소에서 수행되며 데이터 액세스 계층 변경으로 인해 BL이 변경되지 않습니다.
Valery

대부분의 경우 분산 캐시가 ORM에 내장되지 않습니까?
user1450877

나는 그것이 ORM에 달려 있다고 생각합니다. NHibernate 또는 EF보다 가벼운 ORM을 사용하기로 결정할 수 있습니다.
Valery

2

1) ORM을 끄려면 어떻게해야합니까? 저장소에 ORM 코드가 없으면 응용 프로그램에 특정 ORM 코드가 있어야합니다.

나는 회사가 갑자기 데이터 액세스 기술을 전환하기로 결정한 위치에 아직 없었다. 이런 일이 발생하면 약간의 작업이 필요합니다. 인터페이스를 통해 데이터 액세스 작업을 추상화하는 경향이 있습니다. 리포지토리는이를 해결하는 한 가지 방법입니다.

그런 다음 데이터 액세스 계층을 구체적으로 구현하기 위해 다른 어셈블리를 갖게됩니다. 예를 들어, 나는 가질 수 있습니다 :

Company.Product.DataCompany.Product.Data.EntityFramework어셈블리. 다른 어셈블리가 Entity Framework의 데이터 액세스 논리를 구체적으로 구현하는 경우 첫 번째 어셈블리는 인터페이스 용으로 만 사용됩니다.

2) ORM을 사용하지 않고 데이터 액세스 및 오브젝트 데이터 채우기에 ADO.net을 사용하는 경우에도 저장소 패턴이 여전히 유효합니까?

어떤 패턴이 유효한지 결정하는 것은 당신에게 달려 있다고 생각합니다. 프레젠테이션 레이어에서 리포지토리 패턴을 사용했습니다. 명심해야 할 것은 사람들이 저장소에 책임을 던지는 것을 좋아한다는 것입니다. 알기 전에 리포지토리 수업은 춤, 노래 및 모든 종류의 일을합니다. 이것을 피하고 싶다.

GetAll, GetById, Update 및 Delete 책임을 가짐으로써 시작된 리포지토리 클래스를 보았습니다. 프로젝트가 완료 될 무렵, 같은 클래스에는 수십 가지의 방법 (책임)이 있었으며,이 방법은 없었습니다. 예를 들어 GetByForename, GetBySurname, UpdateWithExclusions 및 모든 종류의 미친 것들.

여기에서 쿼리와 명령이 작동합니다.

3) ORM을 사용하지만 저장소 패턴은 사용하지 않는 경우 일반적으로 사용되는 조회를 어디에 보관합니까? 각 쿼리를 클래스로 표현하고 인스턴스를 생성하는 일종의 쿼리 팩토리를 갖는 것이 현명합니까?

리포지토리 대신 쿼리와 명령을 사용하는 것이 좋습니다. 나는 다음을한다 :

  • 쿼리에 대한 인터페이스를 정의하십시오. 이것은 단위 테스트에 도움이됩니다. 예 :public interface IGetProductsByCategoryQuery { ... }

  • 쿼리에 대한 구체적인 구현을 정의하십시오. 선택한 IoC 프레임 워크를 통해 이들을 주입 할 수 있습니다. 예 :public class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

이제는 수십 가지 책임이있는 오염 저장소를 오염시키는 대신 쿼리를 네임 스페이스로 그룹화하기 만하면됩니다. 예를 들어, 위 쿼리에 대한 인터페이스는 다음에있을 수 Company.SolutionName.Products.Queries있으며 구현은Company.SolutionName.Products.Queries.Implementation

데이터 업데이트 또는 제거와 관련하여 동일한 방식으로 명령 패턴을 사용합니다.

어떤 사람들은 프로젝트가 완료되기 전에 수십 개의 클래스와 네임 스페이스를 가질 것이라고 동의하지 않을 수도 있습니다. 네 그렇습니다. 내 마음에 그것은 당신이 선택한 IDE에서 솔루션을 탐색하고 특정 구성 요소가 어떤 종류의 책임을 즉시 볼 수 있기 때문에 좋은 것입니다. 리포지토리 패턴을 대신 사용하기로 결정한 경우 각 리포지토리 클래스를 살펴보고 해당 책임을 해결해야합니다.


나는 일반적인 함수 대신 명령을 갖는 아이디어를 좋아합니다. 데이터 액세스 컨텍스트에서 구현하는 방법에 대한 자세한 내용은 어디서 볼 수 있습니까?
ankush981

1

면책 조항 : 다음은 상기 패턴 (즉, 저장소)에 대한 나의 이해와 간략한 경험에 근거합니다. 나는 그것을 잘못하고있을 수 있습니다 ... 사실, 나는 내가 잘못하고 있다고 꽤 긍정적입니다 :). 따라서 이것은 답변을위한 시도이지만 변장의 문제이기도합니다.

리포지토리 패턴을 사용하여 대부분의 경우 ORM 인 데이터 액세스 계층을 추상화합니다. 지금까지 LINQ to SQL 및 EF에 대한 작성, 읽기, 업데이트, 삭제 및 구현 클래스에 대한 메소드가있는 일반 인터페이스입니다. 디스크의 XML 파일에 쓰는 구현을 만들 수 있습니다 (내가 할 수있는 일에 대한 야생의 예). ORM이 지원하는 작업 단위를 구현하고 있지 않습니다. 필요한 경우 아마도 구현할 수 있습니다. 나는 지금까지 나에게 멋진 분리를 제공했기 때문에이 방법을 좋아한다. 더 나은 대안이 없다고 말하는 것은 아닙니다.

질문에 대답하려면 :

  1. 당신이 그것을 좋아하든 아니든, 변화가 일어날 것입니다. 그리고 많은 응용 프로그램을 작성하고이를 유지하기 위해 시간이되었지만 현재 ORM과 함께 작업하고 변경하려는 고통이 있다고 느끼면 그러한 추상화를 만든 것에 대해 스스로를 칭찬 할 것입니다. 리포지토리 또는 다른 패턴 / 개념과 같이 편안하다고 생각되는 것을 사용하십시오.
  2. 예, 데이터 액세스를 분리하는 데 사용하는 한 가능합니다. 앞에서 언급했듯이 플랫 파일에 데이터를 쓰는 구현을 만들 수 있습니다.
  3. 리포지토리를 사용 하여 조정하려는 쿼리가 많을 때 일반적으로 사용되는 쿼리 및 쿼리 개체 를 유지 합니다.

다른 예를 들기 위해 Umbraco의 직원들은 DI 컨테이너를 추상화하여 다른 것으로 전환하려고 할 수 있습니다.


0

ORM이 LINQ의 유연성, 열성적인 로딩 등을 제공한다면 추가 레이어 뒤에 숨기지 않을 것입니다.
원시 SQL (마이크로 ORM)이 포함 된 경우 재사용 가능성을 달성하기 위해 "쿼리 당 방법"을 사용해야하므로 리포지토리 패턴이 적합합니다.

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

왜 전환해야합니까?
필요한 대부분의 기능이있는 기능을 사용해야합니다. ormX의 새로운 릴리스가 새로운 기능을 제공하고 현재 기능보다 더 나은 것으로 판명 될 수 있지만 ...
orm을 숨기도록 선택하면 모든 후보자가 공통적으로 사용하는 기능 만 사용할 수 있습니다.
예 : 당신은 사용할 수 없습니다 Dictionary<string, Entity>ormY 그를 처리 할 수 있기 때문에 당신의 엔티티에 속성을.

LINQ를 가정하면 ORM 스위치의 대부분은 라이브러리 참조를 전환하고 대체하고, 사용 session.Query<Foo>()context.Foos는 컴파일 될 때까지 또는 유사한. 지루한 작업이지만 추상화 계층을 코딩하는 것보다 시간이 덜 걸립니다.

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

예. 코드는 재사용 가능해야하며 이는 SQL 작성, 객체 구체화 등을 한 곳에 (별도의 클래스) 배치하는 것을 의미합니다. "XRepository"클래스를 호출하고 인터페이스를 추출 할 수도 있습니다.

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

LINQ가 사용된다고 가정하면 클래스 래퍼는 과도한 IMHO가 될 것입니다. 더 좋은 방법은 확장 방법입니다.

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

여러 장소에서 사용되거나 잠재적 인 코드가 충분히 복잡하고 (오류가 발생하기 쉬운) 코드는 중앙 위치로 추출해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.