IQueryable을 반환하려면 IQueryable을 반환하지 않거나
LINQ to SQL Data Context를 래핑하는 리포지토리 클래스가 있습니다. 저장소 클래스는 모든 데이터 계층 논리 (및 캐싱 등)를 포함하는 비즈니스 라인 클래스입니다.
다음은 내 repo 인터페이스의 v1입니다.
public interface ILocationRepository
{
IList<Location> FindAll();
IList<Location> FindForState(State state);
IList<Location> FindForPostCode(string postCode);
}
그러나 FindAll에 대한 페이징을 처리하기 위해 IList 대신 IQueryable <ILocation>을 노출하여 페이징과 같은 상황에 대한 인터페이스를 단순화할지 여부를 논의하고 있습니다.
데이터 저장소에서 IQueryable을 노출하는 것에 대한 장단점은 무엇입니까?
어떤 도움이라도 대단히 감사합니다.
전문가; 구성 가능성 :
- 발신자는 필터를 추가 할 수 있습니다.
- 호출자는 페이징을 추가 할 수 있습니다.
- 발신자는 정렬을 추가 할 수 있습니다.
- 기타
단점; 비 테스트 가능성 :
- 리포지토리는 더 이상 단위 테스트가 가능하지 않습니다. 이 작업 B : 당신이 의지 할 수없는 어떤 것이가하는;
- 호출자는 번역 할 수없는 함수를 추가 할 수 있습니다 (예 : TSQL 매핑 없음, 런타임시 중단)
- 호출자는 개처럼 작동하도록 필터 / 정렬을 추가 할 수 있습니다.
- 호출자는
IQueryable<T>
구성 가능할 것으로 기대 하므로 구성 할 수없는 구현을 배제하거나 사용자가 직접 쿼리 공급자를 작성해야합니다. - DAL을 최적화 / 프로파일 링 할 수 없음을 의미합니다.
안정성을 위해 나는 내 저장소를 노출 하거나 노출 하지 않았습니다 . 이것은 내가 저장소가 어떻게 동작하는지 알고 있다는 것을 의미하며, 내 상위 계층은 "실제 저장소가 이것을 지원합니까?"라는 걱정없이 모의를 사용할 수 있습니다. (강제 통합 테스트).IQueryable<T>
Expression<...>
나는 여전히 저장소 내부 에서 IQueryable<T>
etc를 사용 하지만 경계를 넘어서는 안됩니다. 나는 여기에이 주제에 대한 생각을 더 올렸다 . 리포지토리 인터페이스에 페이징 매개 변수를 넣는 것도 쉽습니다. 확장 메서드 (인터페이스에서)를 사용하여 선택적 페이징 매개 변수 를 추가 할 수도 있습니다 . 따라서 구체적인 클래스에는 구현할 메서드가 1 개만 있지만 호출자가 사용할 수있는 오버로드는 2 개 또는 3 개입니다.
이전 답변에서 언급했듯이 IQueryable을 노출하면 호출자에게 IQueryable 자체를 사용할 수있는 액세스 권한이 주어 지거나 위험해질 수 있습니다.
비즈니스 로직의 첫 번째 책임을 캡슐화하는 것은 데이터베이스의 무결성을 유지하는 것입니다.
IList 노출을 계속할 수 있으며 다음과 같이 매개 변수를 변경할 수 있습니다. 이것이 우리가하는 일입니다.
public interface ILocationRepository
{
IList<Location> FindAll(int start, int size);
IList<Location> FindForState(State state, int start, int size);
IList<Location> FindForPostCode(string postCode, int start, int size);
}
크기 == -1이면 모두 반환 ...
다른 방법 ...
여전히 IQueryable을 반환하려면 함수 내에서 IQueryable of List를 반환 할 수 있습니다. 예를 들어 ...
public class MyRepository
{
IQueryable<Location> FindAll()
{
List<Location> myLocations = ....;
return myLocations.AsQueryable<Location>;
// here Query can only be applied on this
// subset, not directly to the database
}
}
첫 번째 방법은 모두가 아닌 더 적은 데이터를 반환하기 때문에 메모리보다 이점이 있습니다.
IEnumerable
대신을 사용 하는 것이 좋습니다 IList
. 더 많은 유연성을 갖게됩니다.
이렇게하면 저장소에서 추가 작업을 수행하지 않고도 실제로 사용할 데이터 부분 만 Db에서 가져올 수 있습니다.
견본:
// Repository
public interface IRepository
{
IEnumerable<Location> GetLocations();
}
// Controller
public ActionResult Locations(int? page)
{
return View(repository.GetLocations().AsPagination(page ?? 1, 10);
}
매우 깨끗하고 간단합니다.
참고 URL : https://stackoverflow.com/questions/718624/to-return-iqueryablet-or-not-return-iqueryablet
'Development Tip' 카테고리의 다른 글
모든 표준 Android 아이콘 리소스는 어디에 있습니까? (0) | 2020.10.24 |
---|---|
정적 변수는 언제 초기화됩니까? (0) | 2020.10.24 |
null 매개 변수가있는 addToBackStack의 의미는 무엇입니까? (0) | 2020.10.24 |
00.0으로 인해 구문 오류가 발생하는 이유는 무엇입니까? (0) | 2020.10.24 |
Android Gradle 5.0 업데이트 : 원인 : org.jetbrains.plugins.gradle.tooling.util (0) | 2020.10.24 |