4

I'm thinking which way to go and can't decide which one is better. Maybe you can give me the killer idea :)

My problem: I have a generic repository built on top of NHibernate. It's interface is very simple, such as Get(object id), Save, Delete etc. Sometime this interface works fine, but sometime it doesn't. For example, several entities in my project has a property named Code (but not all). I want to be able to get an entity not only by primary key, but also with this property. Another situation is when I need to filter some entities with dates, or provide other filtering criteria which are specific to individual entities. Currently I'm thinking of the following solutions:

  • Linq - I can return an IQueryable object from Repository for each type, then filter the query using linq expressions. I don't like this idea, because if I go this way, I don't see the reason behind Repository.
  • Entity specific repository - Here I can build an entity specific on top of the generic repository. It will have methods such as Get(DateTime dateFrom, DateTime dateTo) etc. The drawback is that I'll have to create a repository class for each entity object. The good side is that it will be much easyer to persist/delete an object graph from database, because it knows entity's dependencies.
  • You tell me please :)
Davita
  • 8,928
  • 14
  • 67
  • 119

5 Answers5

3

Given that you already have a generic repository interface (I assume) I would go with the Entity specific repository, but implement it by extending your generic repository. This should make the code more discoverable and allow you to continue to adhere to your repository pattern. This will allow you to add methods for getting by Code and for getting by passing in a date range.

Joel Briggs
  • 1,779
  • 2
  • 14
  • 17
  • Thanks Joel, your answer is also helpful, so vote up. and P.S. In my situation, I prefer using composition. +1 – Davita Feb 24 '11 at 16:39
  • Thanks! You could still extend the interface, yet use composition by leveraging the generic repository in the implementation of your entity specific repository (Similar to selected answers linked question). – Joel Briggs Feb 24 '11 at 17:11
3

I prefer entity-specific repositories, after putting a lot of effort into generic repositories.

This answer of mine (36 votes so far) elaborates on this stance and contains an approach you might be able to use:

Advantage of creating a generic repository vs. specific repository for each object?

Community
  • 1
  • 1
Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • 37 now ;) Funnily enough I was going through this recently. I wanted to use traditional patterns to see how the approach would work, and using the Repository raised all sorts of issues, my problem almost always was "I can always think of a specific case that I can't support with a general approach. I eventually went with private general repositories and public domain specific repositories which enforce domain relational rules. I still have some issues to iron out when I use nHibernate, but nothing killer. – Ian Feb 24 '11 at 16:34
  • After reading your answer (Advantage of creating a generic repository vs. specific repository for each object?) it's much clear now which way I should go and why. Thanks Bryan :) – Davita Feb 24 '11 at 16:36
2

I advocate using aggregate repositories rather than entity specific repositories. For example, if you have entities

Project
ProjectStatus
ProjectType

it makes sense to combine the data access to all these in a single repository instead of three separate ones.

Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
0

I use something that looks like this: Note, its for Entity Framework but the model/design could be used anywhere I guess.

public interface IRepository<T>
{
    T Save(T entity);
    void Delete(T entity);
    IQueryable<T> GetAll();
    T GetById(int id);
}

I picked it up from a number of questions that debate on using IQueryable, the whole advantage is, you can mock IRepository easily.

See this answer for full details.

Community
  • 1
  • 1
gideon
  • 19,329
  • 11
  • 72
  • 113
  • Yes, that's what I have now, and I was thinking if there were any better solution then working directly with IQueryable – Davita Feb 24 '11 at 16:32
  • @Davita oh, well, like I said, I took it up based on many questions on SO, see the answer I linked. I've mentioned there two such posts. The annoying bit is for 20 entities I have 20 separate IRepos but, I can mock them pretty nicely with Moq. – gideon Feb 24 '11 at 16:36
  • A few comments: Question GetById should probably be T GetById. I sometimes use a IRepository pattern were K is the type of the primary key. And rather than have a GetAll method, I have IRepository actually extend IQueryable...the repository itself is queryable. – Rich Feb 24 '11 at 22:09
  • @rich thanks! corrected. See link for extending IQ .. how would you mock your repo then? http://stackoverflow.com/questions/164342/should-repositories-implement-iqueryablet – gideon Feb 25 '11 at 03:40
0

You can use named queries to get rows based on column that is not a key or do any kind of filtering using Hibernate Query Language (hql) which is pretty similar to sql statements.

This might help.

Prasanna
  • 3,703
  • 9
  • 46
  • 74