itsource

리포지토리 패턴을 올바르게 사용하는 방법

mycopycode 2023. 6. 26. 21:18
반응형

리포지토리 패턴을 올바르게 사용하는 방법

저장소를 어떻게 그룹화해야 하는지 궁금합니다.제가 asp.net mvc와 제 책에서 본 예들처럼 그들은 기본적으로 데이터베이스 테이블당 하나의 저장소를 사용합니다.하지만 이것은 많은 저장소들이 여러분을 나중에 조롱하거나 그런 것들 때문에 많은 저장소들을 불러와야 하는 것처럼 보입니다.

그래서 저는 그들을 그룹으로 묶어야 한다고 생각합니다.하지만 나는 그들을 어떻게 묶어야 할지 잘 모르겠습니다.

지금 저는 제 모든 등록 사항을 처리하기 위해 등록 저장소를 만들었습니다.그러나 업데이트해야 하는 테이블이 4개 정도 있고 이를 위해 저장소가 3개 있기 전에 업데이트해야 합니다.

예를 들어 테이블 중 하나는 라이센스 테이블입니다.그들이 등록할 때 나는 그들의 키를 보고 데이터베이스에 존재하는지 확인합니다.등록이 아닌 다른 장소에서 이 라이센스 키 또는 테이블의 다른 항목을 확인해야 할 경우 어떻게 됩니까?

한 지점은 로그인일 수 있습니다(키가 만료되지 않았는지 확인하십시오).

그렇다면 이 상황에서 제가 무엇을 해야 할까요?코드를 다시 쓰시겠습니까(브레이크 DRY)?이 두 저장소를 병합하여 다른 시점에 어떤 메소드도 필요하지 않기를 바랍니다(예: userName 사용 여부를 확인하는 메소드가 있을 수 있음 - 다른 곳에서 필요할 수 있음).

또한 이들을 병합할 경우 사이트의 서로 다른 두 부분에 대한 논리를 모두 갖추는 데는 시간이 오래 걸리고 ValidateLogin(), ValidateRegistrationForm(), ValidateLoginRetrievePassword() 등의 이름이 필요하기 때문에 동일한 저장소로 이동하는 서비스 계층 2개가 필요합니다.

아니면 어쨌든 저장소에 전화해서 이상하게 들리는 이름을 가지고 있습니까?

일반적인 이름을 가진 저장소를 만들어 응용 프로그램의 여러 지점에 사용할 수 있지만 여전히 의미가 있는 저장소를 만드는 것은 어려울 것 같습니다. 저장소에 있는 다른 저장소를 호출하는 것은 좋은 방법이 아니라고 생각합니다.

저장소 패턴을 가지고 놀 때 제가 잘못한 한 가지는 - 당신처럼, 저도 그 테이블이 저장소 1:1과 관련이 있다고 생각했습니다.도메인 기반 설계의 일부 규칙을 적용하면 리포지토리 그룹화 문제가 종종 사라집니다.

리포지토리는 테이블이 아닌 Aggregate 루트 단위여야 합니다.그것은 - 실체가 혼자 살면 안 되는 경우 (즉, 당신이 가지고 있는 경우)를 의미합니다.Registrant 특히참는하에 Registration - 가 속한 생성/해야 합니다.) - 엔일티뿐이생, 리삭않필으며지루가해, 속개트가한토리의리지합를체다포통트당업성해이니데제야해며하요티리포토지생삭▁),/▁it제//해ved야합)성rie다니▁through▁entity'▁-▁it루▁-▁be▁reposret▁root▁an트/통를트리s토리,▁it/▁it▁just/itory▁of업created이해▁updated지의포데

물론, 대부분의 경우 저장소 수를 줄이는 이 기술(실제로는 도메인 모델을 구성하는 기술)은 적용할 수 없습니다. 모든 엔티티가 집계 루트여야 하기 때문입니다(도메인에 크게 의존하므로 맹목적인 추측만 제공할 수 있습니다).- 예를들어 -License의 컨텍스트 없이 확인할 수 있어야 하기 때문에 집계 루트인 것 같습니다.Registration독립체.

하지만 해서 우리가 캐스케이드 (cascade repository로되는 것은 .Registration는 리지토리수있다니습참조를 참조할 수 있습니다.License필요한 경우 저장소).그것은 우리가 참조하도록 제한하지 않습니다.License우선 - 를 저장권(직장 - IoC통)에서 사용할 수 있습니다.Registration물건.

기술이 제공하는 복잡성이나 오해로 인해 설계를 추진하지 않도록 하십시오.에서 리포지토리 ServiceX단지 2개의 저장소를 구축하고 싶지 않다고 해서 좋은 생각은 아닙니다.

적절한 이름을 붙이는 것이 훨씬 더 나을 것입니다.RegistrationService

그러나 서비스는 일반적으로 피해야 합니다. 서비스는 종종 빈약한 도메인 모델로 이어집니다.


IoC 합니다.그것은 진정으로 의존성을 주입하는 고통을 덜어줍니다.
쓰는대신:

var registrationService = new RegistrationService(new RegistrationRepository(),  
      new LicenseRepository(), new GodOnlyKnowsWhatElseThatServiceNeeds());

다음과 같이 쓸 수 있습니다.

var registrationService = IoC.Resolve<IRegistrationService>();

추신. 공통 서비스 로케이터라는 을 사용하는 것이 낫겠지만, 그것은 단지 예시일 뿐입니다.

이 문제를 해결하기 위해 제가 시작한 한 가지 일은 N개의 저장소를 감싸는 서비스를 실제로 개발하는 것입니다.DI 또는 IoC 프레임워크가 이를 더 쉽게 만들 수 있기를 바랍니다.

public class ServiceImpl {
    public ServiceImpl(IRepo1 repo1, IRepo2 repo2...) { }
}

이해 하셨나요?또한, 이 장에서의 서비스에 대해 말하자면 DDD 원칙을 실제로 준수할 수도 있고 그렇지 않을 수도 있다는 것을 이해합니다. 단지 효과가 있을 것 같아서 그렇게 하는 것입니다.

제가 하고 있는 것은 다음과 같이 정의된 추상 기본 클래스가 있다는 것입니다.

public abstract class ReadOnlyRepository<T,V>
{
     V Find(T lookupKey);
}

public abstract class InsertRepository<T>
{
     void Add(T entityToSave);
}

public abstract class UpdateRepository<T,V>
{
     V Update(T entityToUpdate);
}

public abstract class DeleteRepository<T>
{
     void Delete(T entityToDelete);
}

그런 다음 추상 기본 클래스에서 리포지토리를 파생하고 일반 인수가 다른 경우에는 단일 리포지토리를 확장할 수 있습니다.

public class RegistrationRepository: ReadOnlyRepository<int, IRegistrationItem>,
                                     ReadOnlyRepository<string, IRegistrationItem> 

등등..

일부 저장소에 제한이 있기 때문에 최대의 유연성을 제공하기 때문에 별도의 저장소가 필요합니다.이게 도움이 되길 바랍니다.

저는 이것을 리포지토리 클래스로 가지고 있으며 예, 테이블/영역 리포지토리에서 확장하지만 여전히 때때로 DRY를 해제해야 합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MvcRepository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        protected System.Data.Linq.DataContext _dataContextFactory;

        public IQueryable<T> All()
        {
            return GetTable.AsQueryable();
        }

        public IQueryable<T> FindAll(Func<T, bool> exp)
        {
            return GetTable.Where<T>(exp).AsQueryable();
        }

        public T Single(Func<T, bool> exp)
        {
            return GetTable.Single(exp);
        }

        public virtual void MarkForDeletion(T entity)
        {
            _dataContextFactory.GetTable<T>().DeleteOnSubmit(entity);
        }

        public virtual T CreateInstance()
        {
            T entity = Activator.CreateInstance<T>();
            GetTable.InsertOnSubmit(entity);
            return entity;
        }

        public void SaveAll()
        {
            _dataContextFactory.SubmitChanges();
        }

        public Repository(System.Data.Linq.DataContext dataContextFactory)
        {
            _dataContextFactory = dataContextFactory;
        }

        public System.Data.Linq.Table<T> GetTable
        {
            get { return _dataContextFactory.GetTable<T>(); }
        }

    }
}

편집

public class AdminRepository<T> : Repository<T> where T: class
{
    static AdminDataContext dc = new AdminDataContext(System.Configuration.ConfigurationManager.ConnectionStrings["MY_ConnectionString"].ConnectionString);

    public AdminRepository()
        : base( dc )
    {
    }

Linq2SQL.dbml 클래스를 사용하여 만든 데이터 컨텍스트도 가지고 있습니다.

이제 모두 및 찾기와 같은 표준 호출을 구현하는 표준 저장소가 있으며 관리 저장소에는 특정 호출이 있습니다.

DRY의 질문에 답하지는 않지만, 제 생각에는 그렇지 않습니다.

다음은 Fluent를 사용한 일반 Repository 구현의 입니다.NH 자치주.맵을 작성한 모든 클래스를 지속할 수 있습니다.매퍼 클래스를 기반으로 데이터베이스를 생성할 수도 있습니다.

는 당신이 샤프 건축을 볼 것을 제안합니다.엔티티당 하나의 리포지토리를 사용할 것을 제안합니다.저는 현재 프로젝트에 사용하고 있으며 결과에 매우 만족합니다.

리포지토리 패턴이 잘못된 설계 패턴입니다.저는 많은 노인들과 일합니다.Net 프로젝트 및 이 패턴은 일반적으로 "분산 트랜잭션", "부분 롤백" 및 "연결 풀이 모두 사용됨" 오류를 유발하며 이 오류는 피할 수 있습니다.문제는 패턴이 내부적으로 연결 및 트랜잭션을 처리하려고 하지만 컨트롤러 계층에서 처리해야 한다는 것입니다.또한 EntityFramework는 이미 많은 논리를 추상화합니다.공유 코드를 재사용하는 대신 서비스 패턴을 사용하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/1495553/how-to-use-the-repository-pattern-correctly

반응형