2
votes

I'm trying to build a simple Search functionality into an application using repository pattern, domain models, and a service layer.

I've searched around and haven't found anything that fits the repository pattern. I've had a quick read on the Specification method, but that doesn't look like it will fit what I require. Please read on.

A typical search would involve: Find a student that goes to college xyz, and studies subject abc, and speaks english, and... So, I'm hitting each table essentially.

I have the following layers:

Service layer

AppStudentService, AppCollegeService, ...

Business Logic Layer (BLL) which contains the following domain models:

Student, College, Subject, Language, SearchService ...

Data Access Layer (DAL) which contains the following repositories:

StudentRepository, CollegeRepository, SubjectRepository, LanguageRepository

To attack this problem, I built an AppSearchService in the Service layer. This instantiates the SearchService in the BLL, and all required repositories in the DAL.

In the BLL I built a SearchService which contains the search logic and calls a SubSearch() method on each of the repositories to fetch data for it's area, e.g. StudentRepository.SubSearch returns student(s) details. The business logic will tie up all the sub-search results together for the final search results to be returned.

I decided to break the search into a number of small queries, i.e. SubSearch methods, rather than a massive search query which would contain many joins. Using Entity Framework.

Question 1.

Each repository has it's standard methods, e.g. Add, Save, Remove, FindAll, FindBy, and a SubSearch method. Is adding my custom (non-repo) method a good idea here, or does it contaminate the repository design?

Question 2.

Would it be better put all the SubSearch methods and search logic together into a new Search class (and method) in the DAL? This way all the logic is together and doesn't require instantiating all the BLL objects and Repo objects, i.e. better performance.

Question 3.

Is what I've done a good approach for the repository pattern? If not can someone point me in the right direction, thanks.

2

2 Answers

1
votes

When it comes to question one and question three. This is my repository:

public interface IRepository<T>
{
    IQueryable<T> List();
    bool Create(T item);
    bool Delete(int id);
    T Get(int id);
}

That is all. Repository is for basic access and is used just to cover implementations of these functions in different database access libraries. It is generic class with generic implementation.

About question two. I am not sure what you mean, but I would create IStudentSearchService with method Search, that takes criteria object. It would use repositories (injected in constructor). You inject only repositories used by search functionality. It doesn't even matter how many of them you inject, creating repository should cost much and shouldn't make database operations. This service can have many private methods to prepare additional data for searching.

1
votes

You would be better off create a SearchRepository, that is used to search across your data layer. This will be the most efficient, because joining the results of multiple repositories together is going to be ugly, and inefficient at best. A nightmare to maintain at worst.

You don't want to perform multiple queries for a search if you don't have to. You should perform the query as a single unit. This is most efficient.