0

I'm trying to build a new application using the Repository pattern for the first time and I'm a little confused about using a Repository. Suppose I have the following classes:

public class Ticket
{

}
public class User
{
   public List<Ticket>AssignedTickets { get; set; }
}
public class Group
{
   public List<User> GroupMembers { get;set; }
   public List<Ticket> GroupAssignedTickets { get;set; }
}

I need methods that can populate these collections by fetching data from the database.

I'm confused as to which associated Repository class I should put those methods in. Should I design my repositories so that everything returning type T goes in the repository for type T as such?

public class TicketRepository
{
   public List<Ticket> GetTicketsForGroup(Group g) { }
   public List<Ticket> GetTicketsForUser(User u) { }
}
public class UserRepository
{
  public List<User> GetMembersForGroup(Group g) { }
}

The obvious drawback I see here is that I need to start instantiating a lot of repositories. What if my User also has assigned Widgets, Fidgets, and Lidgets? When I populate a User, I need to instantiate a WidgetRepository, a FidgetRepository, and a LidgetRepository all to populate a single user.

Alternatively, do I construct my repository so that everything requesting based on type T is lumped into the repository for type T as listed below?

public class GroupRepository
{
    public List<Ticket> GetTickets(Group g) { }
    public List<User> GetMembers(Group g) { }
}
public class UserRepository
{
   public List<Ticket> GetTickets(User u) { }
}

The advantage I see here is that if I now need my user to have a collection of Widgets, Fidgets, and Lidgets, I just add the necessary methods to the UserRepository pattern and don't need to instantiate a WidgetRepository, FidgetRepository, and LigetRepository class every time I want to create a user, but now I've scattered the concerns for a user across several different repositories.

I'm really not sure which way is right, if any. Any suggestions?

0

The second option seems like you are defining your repository based on your requirements for this given application vs 1 repository per "table" which could be more flexible for other areas of your app that might come up or other applications that might not group stuff like your current app does. Yes, it means you'll have a fair amount of repositories, but then they are reusable inside any project that needs access to said repository.

I generally make repositories per "table" (I work in DB mostly) and then make "service" classes (some say UnitofWork I think) that group repositories and has an interface to give functionality to that service.

  • 3
    I see it the other way around. My understanding is that the Repository Pattern is a DDD pattern. As such, you're trying to create a useful abstraction for fetching Domain Entities. Since your DB doesn't necessarily need to model 1-table to 1-entity creating a repository per table seems like a bad idea. You'd essentially be coupling your repositories to your DB implementation (which could change) instead of your Domain Model. – MetaFight Jul 31 '14 at 14:06
  • I guess that's why I put table in quotes. They don't have to be an actual DB table (but usually in my case they are), but they are application "tables". He seems to be wanting to group these "tables" together. I still think they would be separate and used in a service. Anything can change at any point which would require changes somewhere. – user441521 Jul 31 '14 at 14:25
  • @MetaFight abstracting the persistence layer is one of the things repository is used for – devnull Jul 31 '14 at 14:36
  • 2
    I'm with @MetaFight. "Defining your repository based on your requirements for this specific application" is exactly how it should be done. I also consider "repository per table" as an anti-pattern, since it doesn't really deal with the application's needs, unless the application is of the simplest "forms over data" form. – Eric King Jul 31 '14 at 14:39
  • 3
    Actually, the abstraction that provides a 1 to 1 mapping to your database tables should be the ORM. The Repository (or Service Layer) should have methods that relate to units of work, such as completing an order or transferring funds. – Robert Harvey Jul 31 '14 at 16:09
0

As it turns out, the first option was the more practical option in this case. There were a few reasons for this:

1) When making changes to a type and its associated repository (assume Ticket), it was far easier to modify the Ticket and TicketRepository in one place than to chase down every method in every repository that used a Ticket.

2) When I attempted to use interfaces to dictate the type of queues each repository could pull, I ran into issues where a single repository couldn't implement an generic interface using type T multiple times with the only differentiation in interface method implementation being the parameter type.

3) I access data from SharePoint and a database in my implementation, and created two abstract classes to provide data tools to the concrete repositories for either Sharepoint or SQL Server. Assume that in the example above Users come from Sharepoint while Tickets come from a database. Using my model I would not be able to use these abstract classes, as the group would have to inherit from both my Sharepoint abstract class and my SQL abstract class. C# does not support multiple inheritance of abstract classes. However, if I'm grouping all Ticket-related behaviours into a TicketRepository and all User-related behaviours into a UserRepository, each repository only needs access to one type of underlying data source (SQL or Sharepoint, respectively).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.