문제

리포지토리 기반 솔루션의 토대로 LINQ에서 SQL을 사용합니다. 내 구현은 다음과 같습니다.

Irepository

FindAll
FindByID
Insert
Update
Delete

그런 다음 결과를 쿼리하는 데 사용되는 확장 방법이 있습니다.

WhereSomethingEqualsTrue() ...

내 질문은 다음과 같습니다.

내 사용자 저장소에는 N 역할이 있습니다. 역할을 관리하기 위해 역할 저장소를 작성합니까? 이 경로를 가면 수십 개의 리포지토리 (거의 테이블을 제외하고 테이블 당 1 개)를 만들게 될까 걱정됩니다. 테이블 당 저장소가 일반적입니까?

도움이 되었습니까?

해결책

리포지토리가 하나의 엔티티 (테이블)에 특화되도록 저장소를 구축하는 경우 각 엔티티가 위에 나열된 Irepository 인터페이스에 메소드 목록이 있도록하는 경우 실제로 수행하는 작업은 활성 기록 무늬.

당신은해야합니다 절대 아니다 테이블 당 하나의 저장소가 있습니다. 도메인 모델의 골재와 수행하려는 작업을 식별해야합니다. 사용자와 역할은 일반적으로 엄격하게 관련되어 있으며 일반적으로 응용 프로그램은 탠덤에서 동작을 수행합니다. 이는 사용자를 중심으로 한 단일 저장소를 요구하며 밀접하게 관련된 엔티티 세트입니다.

나는 당신이 당신의 게시물에서 당신을 추측하고 있습니다 이 예를 보았습니다. 이 예제의 문제점은 모든 리포지토리가 기본 레벨에서 동일한 CRUD 기능을 공유하고 있지만이를 넘어서 도메인 기능을 구현하지는 않습니다. 이 예제의 모든 리포지토리는 동일하게 보이지만 실제로는 실제 리포지토리가 모두 동일하게 보이지는 않습니다 (여전히 인터페이스해야하지만) 각각의 특정 도메인 작업이 있습니다.

저장소 도메인 작업은 다음과 같아야합니다.

userRepository.FindRolesByUserId(int userID)
userRepository.AddUserToRole(int userID)
userRepository.FindAllUsers()
userRepository.FindAllRoles()
userRepository.GetUserSettings(int userID)

등...

이들은 응용 프로그램이 기본 데이터에서 수행하려는 특정 작업이며 저장소는이를 제공해야합니다. 저장소가 도메인에서 수행 할 원자 연산 세트를 나타내는 것으로 생각하십시오. 일반 저장소를 통해 일부 기능을 공유하고 확장 방법으로 특정 저장소를 확장하려면 앱에 잘 맞는 접근 방식 중 하나입니다.

좋은 경험의 규칙은 희귀한 응용 프로그램이 작업을 완료하기 위해 여러 리포지토리를 인스턴스화해야합니다. 필요가 있지만 앱의 모든 이벤트 핸들러가 6 개의 리포지토리를 저글링하여 사용자의 입력을 취하고 입력이 나타내는 엔티티를 올바르게 인스턴스화하면 설계 문제가있을 수 있습니다.

다른 팁

테이블 당 저장소가 일반적입니까?

아니요,하지만 여전히 여러 개의 저장실이있을 수 있습니다. 집계 주위에 저장소를 구축해야합니다.

또한 모든 리포지토리에서 일부 기능을 추상화 할 수 있습니다.

일반적인 방식 으로이 모든 공통 기능을 구현하는 기본 저장소를 구현할 수 있습니다.

다음 예는이 점을 증명하는 것만으로 만 사용됩니다. 아마도 많은 개선이 필요할 것입니다 ...

    interface IRepository<T> : IDisposable where T : class
    {
        IEnumerable<T> FindAll(Func<T, bool> predicate);
        T FindByID(Func<T, bool> predicate);
        void Insert(T e);
        void Update(T e);
        void Delete(T e);
    }

    class MyRepository<T> : IRepository<T> where T : class
    {
        public DataContext Context { get; set; }

        public MyRepository(DataContext context)
        {
            Context = Context;
        }

        public IEnumerable<T> FindAll(Func<T,bool> predicate)
        {
            return Context.GetTable<T>().Where(predicate);
        }

        public T FindByID(Func<T,bool> predicate)
        {
            return Context.GetTable<T>().SingleOrDefault(predicate);
        }

        public void Insert(T e)
        {
            Context.GetTable<T>().InsertOnSubmit(e);
        }

        public void Update(T e)
        {
            throw new NotImplementedException();
        }

        public void Delete(T e)
        {
            Context.GetTable<T>().DeleteOnSubmit(e);
        }

        public void Dispose()
        {
            Context.Dispose();
        }
    }

저에게 저장소 패턴은 데이터 액세스 방법론에 얇은 래퍼를 넣는 것입니다. 귀하의 경우 LINQ에서 SQL이지만 NHibernate는 다른 사람들에게 손으로 롤링되었습니다. 내가 찾은 것은 테이블 당 저장소를 만드는 것입니다. 그것은 사물을 찾고 CRUD 운영을 수행하는 책임이 있습니다.

그러나 요하네스가 언급 한 것처럼 집계 뿌리를 더 다루는 서비스 수준이 있습니다. getExistingUser (int id)와 같은 메소드가있는 userservice가 있습니다. 이것은 내부적으로 userreepository.getByid () 메소드를 호출하여 사용자를 검색합니다. 비즈니스 프로세스가 getExistingUser ()가 반환 한 사용자 클래스가 필요한 경우 항상 사용자가 채우려면 항상 user.isinroles () 속성이 필요합니다. 그리고 Rolerepository. 의사 코드에서는 다음과 같이 보일 수 있습니다.

public class UserService
{
    public UserService(IUserRepository userRep, IRoleRepository roleRep) {...}
    public User GetById(int id)
    {
        User user = _userService.GetById(id);
        user.Roles = _roleService.FindByUser(id);
        return user;
}

userrep 및 rolerep는 LINQ에서 SQL 비트로 다음과 같은 것과 같이 구성됩니다.

public class UserRep : IUserRepository
{
    public UserRep(string connectionStringName)
    {
        // user the conn when building your datacontext
    }

    public User GetById(int id)
    {
        var context = new DataContext(_conString);
        // obviously typing this freeform but you get the idea...
        var user = // linq stuff
        return user;
    }

    public IQueryable<User> FindAll()
    {
        var context = // ... same pattern, delayed execution
    }
}

개인적으로 저는 저장소 수업을 내부적으로 범위로 만들고 사용자 서비스 및 기타 XXXXXService 클래스를 공개 할 수 있으므로 서비스 API 소비자에게 정직하게 유지하십시오. 다시 한 번 저장소는 데이터 스토어와 대화하는 행위와 더 밀접하게 연결되어 있지만 서비스 계층이 비즈니스 프로세스의 요구와 더 밀접하게 조정됩니다.

나는 종종 LINQ의 객체와 그 모든 것들에 대한 유연성을 너무 많이 생각하고 iquerable을 사용하는 것을 실제로 발견했습니다. et al 내가 실제로 필요한 것을 뱉어내는 서비스 방법을 구축하는 대신. 사용자 LINQ는 적절한 경우, 그러나 respository가 모든 일을하도록하려고 시도하지 마십시오.

public IList<User> ActiveUsersInRole(Role role)
{ 
    var users = _userRep.FindAll(); // IQueryable<User>() - delayed execution;
    var activeUsersInRole = from users u where u.IsActive = true && u.Role.Contains(role);
    // I can't remember any linq and i'm type pseudocode, but
    // again the point is that the service is presenting a simple
    // interface and delegating responsibility to
    // the repository with it's simple methods.
    return activeUsersInRole;
}

그래서 그것은 약간 끔찍했습니다. 내가 정말로 도움이되었는지 확실하지 않지만, 내 조언은 확장 방법으로 너무 공상을 피하고 다른 레이어를 추가하여 각 부품을 간단하게 유지하는 것입니다. 나를 위해 일합니다.

WOMP가 제안한대로 저장소 계층을 작성하면 서비스 계층에 무엇을 넣을 수 있습니까? 컨트롤러 또는 코드 비인에 사용하기 위해 주로 해당 저장소 메소드에 대한 호출로 구성되는 동일한 메소드 호출을 반복해야합니까? 이것은 귀하가 귀하가 검증, 캐싱, 워크 플로우, 인증/인증 코드를 작성하는 서비스 계층이 있다고 가정합니다. 아니면 내가 기지에서 벗어나?

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