Using LINQ TO SQL as the underpinning of a Repository-based solution. My implementation is as follows:
IRepository
FindAll
FindByID
Insert
Update
Delete
Then I have extension methods that are used to query the results as such:
WhereSomethingEqualsTrue() ...
My question is as follows:
My Users repository has N roles. Do I create a Roles repository to manage Roles? I worry I'll end up creating dozens of Repositories (1 per table almost except for Join tables) if I go this route. Is a Repository per Table common?
If you are building your Repository to be specific to one Entity (table), such that each Entity has the list of methods in your IRepository interface that you listed above, then what you are really doing is an implementation of the Active Record pattern.
You should definitely not have one Repository per table. You need to identify the Aggregates in your domain model, and the operations that you want to perform on them. Users and Roles are usually tightly related, and generally your application would be performing operations with them in tandem - this calls for a single repository, centered around the User and it's set of closely related entities.
I'm guessing from your post that you've seen this example. The problem with this example is that all the repositories are sharing the same CRUD functionality at the base level, but he doesn't go beyond this and implement any of the domain functions. All the repositories in that example look the same - but in reality, real repositories don't all look the same (although they should still be interfaced), there will be specific domain operations associated with each one.
Your repository domain operations should look more like:
etc...
These are specific operations that your application wants to perform on the underlying data, and the Repository should provide that. Think of it as the Repository represents the set of atomic operations that you would perform on the domain. If you choose to share some functionality through a generic repository, and extend specific repositories with extension methods, that's one approach that may work just fine for your app.
A good rule of thumb is that it should be rare for your application to need to instantiate multiple repositories to complete an operation. The need does arise, but if every event handler in your app is juggling six repositories just to take the user's input and correctly instantiate the entities that the input represents, then you probably have design problems.
No, but you can still have several repositiories. You should build a repository around an aggregate.
Also, you might be able to abstract some functionality from all the repositories... and, since you are using Linq-to-Sql, you probably can...
You can implement a base repository which in a generic way implements all this common functionality.
The following example serves only to prove this point. It probably needs a lot of improvement...
To me the repository pattern is about putting a thin wrapper around your data access methodology. LINQ to SQL in your case, but NHibernate, hand-rolled in others. What I've found myself doing is create a repository-per-table for that is extremely simple (like bruno lists and you already have). That is responsible for finding things and doing CRUD operations.
But then I have a service level that deals more with aggregate roots, as Johannes mentions. I would have a UserService with a method like GetExistingUser(int id). This would internally call the UserRepository.GetById() method to retrieve the user. If your business process requires the user class returned by GetExistingUser() to pretty much always need the User.IsInRoles() property to be filled, then simply have the UserService depend upon both the UserRepository and RoleRepository. In pseudo code it could look something like this:
The userRep and roleRep would be constructed with your LINQ to SQL bits something like this:
Personally I would make the repository classes internally scoped and have the UserService and other XXXXXService classes public so keep your consumers of the service API honest. So again I see repositories as more closely linked to the act of talking to a datastore, but your service layer being more closely aligned to the needs of your business process.
I've often found myself really overthinking the flexibility of Linq to Objects and all that stuff and using IQuerable et al instead of just building service methods that spit out what I actually need. User LINQ where appropriate but don't try to make the respository do everything.
So, that was a bit rambling. Not sure if I really helped any, but my advise is to avoid getting too fancy with extension methods, and just add another layer to keep each of the moving parts pretty simple. Works for me.
If we write our repository layer as detailed as Womp suggests, what do we put in our service layer. Do we have to repeat same method calls, which would mostly consists of calls to corresponding repository method, for use in our controllers or codebehinds? This assumes that you have a service layer, where you write your validation, caching, workflow, authentication/authorization code, right? Or am I way off base?