문제

나는 현재 새로운 프로젝트를 설정하고 있으며 약간의 입력이 필요한 몇 가지 사항을 얻었습니다.

이것이 제가 고려하고있는 것입니다.

  • 일반 저장소를 원합니다

  • 저장소에서 iqueryable을 반환하고 싶지 않습니다.

  • 사양에서 쿼리를 캡슐화하고 싶습니다.

  • 사양 패턴을 구현했습니다

  • 쉽게 테스트 할 수 있어야합니다

이제 여기에서 조금 붙어있는 곳이었고 내 질문은 하나 이상의 사양으로 찾기 메소드를 호출하는 가장 우아한 방법이 될 것입니다.

(유창한): bannerRepository.Find().IsAvailableForFrontend().IsSmallMediaBanner()

또는 쿼리를 내 사양으로 lambdas로 표현하십시오

(람다) : bannerRepository.Find.Where(banner => banner.IsFrontendCampaignBanner && banner.IsSmallMediaBanner)

아니면 완전히 다른 방법으로? 가장 중요한 것은 MVC 전선을 구현하는 사람이 저장소에 대한 직관적 인 경험을 가져야한다는 것입니다.

내가 달성하기를 바라는 것은 사양을 결합하고 사양과 "필터링"의 경험을 제공하지만 컨트롤러에 iqueryable을 유출하지 않지만 ispecifiable만으로도 유연하게 유연성을 유지하는 것입니다. LINQ가 아닌 사양으로 쿼리를 수정합니다. 그러나 방금 이런 식으로 쿼리 로직을 컨트롤러로 유출 하는가?

도움이 되었습니까?

해결책

사양에 속성을 사용하는 유창한 API를 보았으므로 클라이언트에 괄호 소음을 추가하지 않습니다.

bannerRepository.Find.IsAvailableForFrontend.IsSmallMediaBanner.Exec()

exec () repo에 대한 사양을 실행하는 메소드입니다.

그러나 속성을 사용하지 않더라도 최소 노이즈가 있기 때문에 유창한 API로 갈 것입니다.

다른 팁

아니면 완전히 다른 방법으로?

글쎄, 실제로 나는 당신의 저장소 구현을 정확히 얻지 못합니다 (예 : 방법은 무엇을 .Find() 반환?), 그러나 나는 다른 방향을 선택할 것입니다.

public class Foo 
{ 
    public Int32 Seed { get; set; }
}

public interface ISpecification<T> 
{
    bool IsSatisfiedBy(T item);
}

public interface IFooSpecification : ISpecification<Foo> 
{
    T Accept<T>(IFooSpecificationVisitor<T> visitor);
}

public class SeedGreaterThanSpecification : IFooSpecification
{
    public SeedGreaterThanSpecification(int threshold)
    {
        this.Threshold = threshold;
    }
    public Int32 Threshold { get; private set; }
    public bool IsSatisfiedBy(Foo item) 
    {
        return item.Seed > this.Threshold ;
    }
    public T Accept<T>(IFooSpecificationVisitor<T> visitor)
    {
        return visitor.Visit(this);
    }
}
public interface IFooSpecificationVisitor<T>
{
    T Visit(SeedGreaterThanSpecification acceptor);
    T Visit(SomeOtherKindOfSpecification acceptor);
    ...
}
public interface IFooRepository 
{
    IEnumerable<Foo> Select(IFooSpecification specification);
}
public interface ISqlFooSpecificationVisitor : IFooSpecificationVisitor<String> { }
public class SqlFooSpecificationVisitor : ISqlFooSpecificationVisitor
{
    public string Visit(SeedGreaterThanSpecification acceptor)
    {
        return "Seed > " + acceptor.Threshold.ToString();
    }
    ...
}
public class FooRepository
{   
    private ISqlFooSpecificationVisitor visitor;

    public FooRepository(ISqlFooSpecificationVisitor visitor)
    {
        this.visitor = visitor;
    }

    public IEnumerable<Foo> Select(IFooSpecification specification)
    {
        string sql = "SELECT * FROM Foo WHERE " + specification.Accept(this.visitor);
        return this.DoSelect(sql);
    }

    private IEnumerable<Foo> DoSelect(string sql)
    {
        //perform the actual selection;
    }
}

따라서 엔티티, 사양 인터페이스 및 방문자 패턴, 사양 인터페이스 및 저장소 구현을 수락하는 저장소 인터페이스와 관련된 몇몇 구현자가 있습니다. 이것 물론 사례). 마지막으로, 저장소 인터페이스 (Fluent Interface 사용) "외부"사양을 작성합니다.

어쩌면 이것은 순진한 아이디어 일지 모르지만, 나는 그것이 매우 간단하다고 생각합니다. 도움이 되었기를 바랍니다.

개인적으로 나는 Lambda Way와 함께 갈 것입니다. Lambda에 대한 나의 사랑 때문일 수 있지만 일반적인 저장소 설정을위한 공간을 제공합니다.

다음을 고려하십시오.

bannerRepository.Find.Where(banner => banner.IsFrontendCampaignBanner && banner.IsSmallMediaBanner)

나는 당신의 패턴이 어떻게 생겼는지 모르겠지만 여기에 몇 가지를 리팩터링 할 수 있습니다.

데이터 액세스를위한 모든 메소드를 포함하는 유형의 'irepository'라는 일반 인터페이스를 만듭니다.

다음과 같이 보일 수 있습니다.

interface IRepository<T> where T : class
{
    IEnumerable<T> FindAll(Func<T, bool> exp);

    T FindSingle(Func<T, bool> exp);
}   

이 인터페이스를 구현하는 추상적 인 '저장소'클래스를 만듭니다.

class Repository<T> : IRepository<T> where T : class
{
    TestDataContext _dataContext = TestDataContext();

    public IEnumerable<T> FindAll(Func<T, bool> exp)
    {
        _dataContext.GetTable<T>().Where<T>(exp);
    }

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

이제 우리의 'irepository'를 구현하는 배너 테이블/객체에 대한 인터페이스와 추상 '저장소'클래스를 확장하고 'ibannerinterface'를 구현하는 콘크리트 클래스를 만들 수 있습니다.

interface IBannerRepository : IRepository<Banner>
{
}

그리고 그것을 구현하기위한 일치하는 저장소 :

class BannerRepository : Repository<Banner>, IBannerRepository
{
}

나는이 접근법을 사용하여 많은 유연성과 당신이 가진 모든 작은 개체를 제어 할 수있는 충분한 힘을 제공하는 것이 좋습니다.

이러한 방법을 호출하는 방식은 매우 쉽습니다.

BannerRepository _repo = new BannerRepository();

_repo.FindSingle(banner => banner.IsFrontendCampaignBanner && banner.IsSmallMediaBanner);

예, 그것은 당신이 약간의 일을해야한다는 것을 의미하지만 나중에 데이터 소스를 변경하는 것이 더 쉽습니다.

도움이되기를 바랍니다!

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