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 a 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 bunch of different repository classes 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?
The repository pattern can help you to:
Put things that change for the same reason together
As well as
Separate things that change for different reasons
On the whole, I would expect a "User Repository" to be a repository for obtaining users. Ideally, it would be the only repository that you can use to obtain users, because if you change stuff, like user tables or the user domain model, you would only need to change the user repository. If you have methods on many repositories for obtaining a user, they would all need to change.
Limiting the impact of change is good, because change is inevitable.
As for instantiating many repositories, using a dependency injection tool such as Ninject or Unity to supply the repositories, or using a repository factory, can reduce new-ing up lots of repositories.
Finally, you can take a look at the concept of Domain Driven Design to find out more about the key purpose behind domain models and repositories (and also about aggregate roots, which are relevant to what you are doing).
Fascinating question with no right answer. This might be a better fit for programmers.stackexchange.com rather than stackoverflow.com. Here are my thoughts:
Don't worry about creating too many repositories. They are basically stateless objects so it isn't like you will use too much memory. And it shouldn't be a significant burden to the programmer, even in your example.
The real benefit of repositories is for mocking the repository for unit testing. Consider splitting them up based on what is simplest for the unit tests, to make the dependency injection simple and clear. I've seen cases where every query is a repository (they call those "queries" instead of repositories). And other cases where there is one repository for everything.
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).
Related
I've been entering the advanced stage of C# recently and I've seen a lot of applications that implement losely coupling and dependency injection. I've seen the word "Service" a lot associated with classes, I suppose you would call them Service classes? I've also seen classes in this project which include the word Repository, say you has a called 'Player', there would be 2 more classes 'PlayerService' and 'PlayerRepository' classes.
I've checked Linda, TreeHouse, Udemy and many other sites. I've even google the subject but it seems to bring up hundreds of results all leading to different things. None of these links really answer my question in simple plain detail, atleast none that I can understand.
Can anyone help explain this? Why do I need them, when should I use them, what are they?
Well, hard to make a specific explanation without seeing the code but in general terms the concept of a Repository refers to data layer components and the term service - mostly in ASP.NET world refers to business layer components.
You separate these layers from each other so they can be maintained, tested, expanded in isolation. Ideal architectures expose the functionality of these layers via Interfaces - especially the Repository layer. On the Service layer you can take these dependencies through constructor as Interfaces. Using an IoC container and Dependency Injection patterns, you can then register concrete classes to these interfaces and build your objects in a central location aka. Object Composition Root. that allows you easily manage your dependencies in a central location, rather then each dependency instantiated, passed around in scattered places within your code.
This answer is just a pointer to give you an overview. These are topics you should delve deeper by self research and digest.
The Repository pattern is used to abstract away how a class is persisted. This allows you to change the underlying Database or ORM mapper without influencing the persisted classes. See Using Repository Pattern for Abstracting Data Access from a Cache and Data Store.
A service is used if multiple classes are taking part in a certain usecase and none of these classes should have the responsibility to coordinate the other classes. (Maybe these classes do not even hold direct references to each other.) In this case, put the code that handles the interplay between the classes into a service method and pass the affected objects to it.
Note that if the affected classes are in a direct parent-child relationship, you could let the parent coordinate its children directly, without introducing a service. But this might lead to code that is hard to understand.
Let me give an example: assume we want to commit Transactions. After a Transaction was commited, we want to update the Person who has the transaction with the (denormalized) timestamp of the most recent transaction. As you can see, Person does not hold a direct reference to the transaction.
public class Person {
public long Id { get; set; }
public string Name { get; set; }
public DateTime? LastTransactionTimestamp { get; set; }
}
public class Transaction {
public long Id { get; set; }
public long PersonId { get; set; }
public DateTime Timestamp { get; set; }
public void Commit() {
Timestamp = DateTime.Now;
}
}
Now we have the problem where we should put the logic. If we put it into the Person class, it would need Repository access to load the Transaction (because it holds no direct reference). But it should only be concerned with storing its own data, not loading unrelated data from the DB. If we put it into the Transaction class, it does not know if it was the latest Transaction for this Person (because it does not see the other transactions).
So the solution is to put the logic into a service. If the service needs DB access, we inject a repository into it.
public class PersonTransactionService {
private readonly IDbSet<Transaction> _allTransactions;
public PersonTransactionService(IDbSet<Transaction> allTransactions) {
_allTransactions = allTransactions;
}
public void Commit(Person person, Transaction transaction) {
transaction.Commit();
var mostRecent = _allTransactions
.Where(t => t.PersonId == person.Id)
.OrderBy(t => t.Timestamp)
.LastOrDefault();
if (mostRecent != null) {
person.LastTransactionTimestamp = mostRecent.Timestamp;
}
}
}
In my earlier question I was asking about implementing repository/unit of work pattern for large applications built with an ORM framework like EF.
One followup problem I cannot come through right now is where to put codes containing business logic, but still lower-level enough to be used commonly in many other part of the application.
For example here is a few such method:
Getting all users in one or more roles.
Getting all cities where a user has privileges within an optional
region.
Getting all measure devices of a given device type, within a given
region for which the current user has privileges.
Finding a product by code, checking if it's visible and throwing
exception if not found or not visible.
All of these methods use a UnitOfWork for data access or manipulation, and receive several parameters as in their specification. I think everyone could write a lot more example for such common tasks in a large project. My question is where shall I put tese method implementations? I can see the following options currently.
Option 1: Every method goes to its own service class
public class RegionServices {
// support DI constructor injection
public RegionServices(IUnitOfWork work) {...}
...
public IEnumerable<City> GetCitiesForUser(User user, Region region = null) { ... }
...
}
public class DeviceServices {
// support DI constructor injection
public DeviceServices(IUnitOfWork work) {...}
...
public IEnumerable<Device> GetDevicesForUser(User user, DeviceType type, Region region = null) { ... }
...
}
What I don't like about it is that if a higher-level application service needs to call for example 3 or these methods, then it needs to instantiate 3 services, and if I use DI then I even have to put all 3 into the constructor, easily resulting quite a bit of code smell.
Option 2: Creating some kind of Facade for such common data access
public class DataAccessHelper {
// support DI constructor injection
public DataAccessHelper(IUnitOfWork work) {...}
...
public IEnumerable<City> GetCitiesForUser(User user, Region region = null) { ... }
public IEnumerable<Device> GetDevicesForUser(User user, DeviceType type, Region region = null) { ... }
public IEnumerable<User> GetUsersInRoles(params string[] roleIds) { ... }
...
}
I don't like it because it feels like violating the SRP, but its usage can be much more comfortable however.
Option 3: Creating extension methods for the Repositories
public static class DataAccessExtensions {
public static IEnumerable<City> GetCitiesForUser(this IRepository repo, User user, Region region = null) { ... }
}
Here IRepository is an interface with generic methods like Query<T>, Save<T>, etc. I don't like it either because it feels like I want to give business logic to repositories which is not advisable AFAIK. However, it expresses that these methods are common and lower level than service classes, which I like.
Maybe there are other options as well?... Thank you for the help.
If you say that a certain piece of domain logic needs to look at 3 distinct pieces of information in order to make a decision then we will need to provide this information to it.
Further if we say that each of these distinct pieces can be useful to other parts of the domain then each of them will need to be in its own method also. We can debate whether each query needs to be housed in a separate class or not depending on your domain/design.
The point I wanted to make is that there will be a application service which delegates to one or more Finder classes (classes where your queries are housed), these classes house only queries and then accumulate the results and pass it down to a Domain Service as method params.
The domain service acts on on the received parameters executes the logic and returns the result. This way the domain service is easily testable.
psuedo code
App Service
result1 = finder.query1()
result2 = finder.query2()
result3= yetanotherfinder.query();
domainresult = domainservice.calculate(result1,result2,result3);
Repositories belong to the domain, queries do not (http://www.jefclaes.be/2014/01/repositories-where-did-we-go-wrong_26.html).
You could define explicit queries and query handlers and use those outside of your domain.
public class GetUserStatisticsQuery
{
public int UserId { get; set; }
}
public class GetUserStatisticsQueryResult
{
...
}
public class GetUserStatisticsQueryHandler :
IHandleQuery<GetUserStatisticsQuery, GetUserStatisticsQueryResult>
{
public GetUserStatisticsQueryResult Handle(GetUserStatisticsQuery query)
{
... "SELECT * FROM x" ...
}
}
var result = _queryExecutor.Execute<GetUserStatisticsQueryResult>(
new GetUserStatisticsQuery(1));
I'm adding my conclusion as an answer, because I quickly realized that this question is quite relative and not exact, heavily depends on personal favours or design trends.
The comments and the answers helped me in seeing more clearly how things like this should basically be implemented, thank you for all of your effort.
Conclusion
A "repository" should be responsible clearly only for data persisting. Because it doesn't hold any domain logic, or type specific logc, I think it can be represented and implemented as an IRepository interface with generic methods like Save<T>, Delete<T>, Query<T>, GetByID<T>, etc. Please refer to my previous question mentioned in the beginning of my original post.
On the other hand, I think (at least now with my current project) that introducing new class/classes for each lower-level domain logic (in the most cases some kind of querying logic) task is a bit over-engineered solution, which is not needed for me. I mean I don't want to introduce classes like GetUsersInRoles or GetDevicesInRegionWithType, etc. I feel I would end up with a lot of classes, and a lot of boilerplate code when refering them.
I decided to implement the 3rd option, adding static query functions as extensions to IRepository. It can be nicely separated in a Queries project folder, and structured in several static classes each named after the underlying domain model on which it defines operations. For example I've implemented user related queries as follows: in Queries folder I've created a UserQueries.cs file, in which I have:
public static class UserQueries {
public static IEnumerable<User> GetInRoles(this IRepository repository, params string[] roles)
{
...
}
}
This way I can easily and comfortable access such methods via extensions on every IRepository, the methods are unit-testable and support DI (as they are callable on any IRepository implementation). This technique fits best for my current needs.
It can be refactored even further to make it even cleaner. I could introduce "ghost" sealed classes like UserQueriesWrapper and use it to structure the calling code and this way not put every kind of such extensions to IRepository. I mean something like this:
// technical class, wraps an IRepository dummily forwarding all members to the wrapped object
public class RepositoryWrapper : IRepository
{
internal RepositoryWrapper(IRepository repository) {...}
}
// technical class for holding user related query extensions
public sealed class UserQueriesWrapper : RepositoryWrapper {
internal UserQueriesWrapper(IRepository repository) : base(repository) {...}
}
public static class UserQueries {
public static UserQueriesWrapper Users(this IRepository repository) {
return new UserQueriesWrapper(repository);
}
public static IEnumerable<User> GetInRoles(this UserQueriesWrapper repository, params string[] roles)
{
...
}
}
...
// now I can use it with a nicer and cleaner syntax
var users = _repo.Users().GetInRoles("a", "b");
...
Thank you for the answers and comments again, and please if there is something I didn't notice or any gotcha with this technique, leave a comment here.
Currently we have implemented a repository pattern at work. All our repositories sit behind their own interfaces and are mapped via Ninject. Our project is quite large and there are a couple quirks with this pattern I'm trying to solve.
First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller. The constructor gets rather ugly when asking for so many repositories. The second quirk reveals itself after you call methods on multiple repositories. After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on? Every repository has one. All repositories have the same instance of the Entity Framework data context injected so picking any random repository to call save on will work. It just seems so messy.
I looked up the "Unit Of Work" pattern and came up with a solution that I think solves both problems, but I'm not 100% confident in this solution. I created a class called DataBucket.
// Slimmed down for readability
public class DataBucket
{
private DataContext _dataContext;
public IReportsRepository ReportRepository { get; set; }
public IEmployeeRepository EmployeeRepository { get; set; }
public IDashboardRepository DashboardRepository { get; set; }
public DataBucket(DataContext dataContext,
IReportsRepository reportsRepository,
IEmployeeRepository employeeRepository,
IDashboardRepository dashboardRepository)
{
_dataContext = dataContext;
this.ReportRepository = reportsRepository;
this.EmployeeRepository = employeeRepository;
this.DashboardRepository = dashboardRepository;
}
public void SaveChanges()
{
_dataContext.SaveChanges();
}
}
This appears to solve both issues. There is now only one SaveChanges method on the data bucket itself and you only inject one object, the data bucket. You then access all the repositories as properties. The data bucket would be a little messy looking since it would be accepting ALL (easily 50 or more) of our repositories in its constructor.
The process of adding a new repository would now include: creating the interface, creating the repository, mapping the interface and repository in Ninject, and adding a property to the data bucket and populating it.
I did think of an alternative to this that would eliminate a step from above.
public class DataBucket
{
private DataContext _dataContext;
public IReportsRepository ReportRepository { get; set; }
public IEmployeeRepository EmployeeRepository { get; set; }
public IDashboardRepository DashboardRepository { get; set; }
public DataBucket(DataContext dataContext)
{
_dataContext = dataContext;
this.ReportRepository = new ReportsRepository(dataContext);
this.EmployeeRepository = new EmployeeRepository(dataContext);
this.DashboardRepository = new DashboardRepository(dataContext);
}
public void SaveChanges()
{
_dataContext.SaveChanges();
}
}
This one pretty much eliminates all the repository mappings in Ninject because they are all instantiated in the data bucket. So now the steps to adding a new repository include: Create interface, create repository, add property to data bucket and instantiate.
Can you see any flaws with this model? On the surface it seems much more convenient to consume our repositories in this way. Is this a problem that has been addressed before? If so, what is the most common and/or most efficient approach to this issue?
First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller.
Say hello to Abstract factory pattern. Instead of registering all repositories in Ninject and injecting them to controllers register just single implementation of the factory which will be able to provide any repository you need - you can even create them lazily only if the controller really needs them. Than inject the factory to controller.
Yes it also has some disadvantages - you are giving controller permission to get any repository. Is it problem for you? You can always create multiple factories for some sub systems if you need or simply expose multiple factory interfaces on single implementation. It still doesn't cover all cases but it is better than passing 15 parameters to constructor. Btw. are you sure those controllers should not be split?
Note: This is not Service provider anti-pattern.
After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on?
Say hello to Unit of Work pattern. Unit of Work is logical transaction in your application. It persists all changes from logical transaction together. Repository should not be responsible for persisting changes - the unit of work should be. Somebody mentioned that DbContext is implementation of Repository pattern. It is not. It is implementation of Unit of Work pattern and DbSet is implementation of Repository pattern.
What you need is central class holding the instance of the context. The context will be also passed to repositories because they need it to retrieve data but only the central class (unit of work) will offer saving changes. It can also handle database transaction if you for example need to change isolation level.
Where should be unit of work handled? That depends where your logical operation is orchestrated. If the operation is orchestrated directly in controller's actions you need to have unit of work in the action as well and call SaveChanges once all modifications are done.
If you don't care about separation of concerns too much you can even combine unit of work and factory into single class. That brings us to your DataBucket.
I think you are absolutely right to use the Unit of Work pattern in this case. Not only does this prevent you from needing a SaveChanges method on every repository, it provides you a nice way to handle transactions from within code rather than in your database itself. I included a Rollback method with my UOW so that if there was an exception I could undo any of the changes the operation had already made on my DataContext.
One thing you could do to prevent weird dependency issues would be to group related repositories on their own Unit of Work, rather than having one big DataBucket that holds every Repository you have (if that was your intent). Each UOW would only need to be accessible at the same level as the repositories it contained, and other repositories should probably not depend on other UOWs themselves (your repositories shouldn't need to use other repositories).
If wanted to be an even bigger purist of the pattern, you could also structure your UOWs to represent just that, a single Unit of Work. You define them to represent a specific operation in your domain, and provide it with the repositories required to complete that operation. Individual repositories could exist on more than one UOW, if it made sense to be used by more than one operation in your domain.
For example, a PlaceCustomerOrderUnitOfWork may need a CustomerRepository, OrderRepository, BillingRepository, and a ShippingRepository
An CreateCustomerUnitOfWork may need just a CustomerRepository. Either way, you can easily pass that dependency around to its consumers, more fine grained interfaces for your UOW can help target your testing and reduce the effort to create a mock.
The notion of every repository having a SaveChanges is flawed because calling it saves everything. It is not possible to modify part of a DataContext, you always save everything. So a central DataContext holder class is a good idea.
Alternatively, you could have a repository with generic methods that can operate on any entity type (GetTable<T>, Query<T>, ...). That would get rid of all those classes and merge them into one (basically, only DataBucket remains).
It might even be the case that you don't need repositories at all: You can inject the DataContext itself! The DataContext by itself is a repository and a full fledged data access layer. It doesn't lend itself to mocking though.
If you can do this depends on what you need the "repository" do provide.
The only issue with having that DataBucket class would be that this class needs to know about all entities and all repositories. So it sits very high in the software stack (at the top). At the same time it is being used by basically everything so it sits at the bottom, too. Wait! That is a dependency cycle over the whole codebase.
This means that everything using it and everything being used by it must sit in the same assembly.
What I have done in the past was to create child injection containers (I was using Unity) and register a data context with a ContainerControlledLifetime. So that when the repositories are instantiated, they always have the same data context injected into them. I then hang on to that data context and when my "Unit of Work" is complete, I call DataContext.SaveChanges() flushing all the changes out to the database.
This has some other advantages such as (with EF) some local caching, such that if more than one repository needs to get the same entity, only the first repository actually causes a database round trip.
It's also a nice way to "batch up" the changes and make sure they execute as a single atomic transaction.
I have a program that deals with (virtual) money order transactions, and there are many classes that has logic requiring data to be saved to a database. My question is if I shall call my repositories directly from the various classes, or if I shall instead raise events, which a DatabaseManager class object can listen to, and hence all repositories will be called from this one class.
I don't have experience working with databases and repositories, so would appreciate some deeper insight and tips here. Like on what criteria you would chose different approach etc.
It's probably important to note that the database in this case is not used to retrieve data for performing program logic, except on program startup. So it's basically keeping all data in runtime objects, and just dumping to database for archiving.
I would pass an IRepository to my classes which they can then call to save data. For one thing it makes testing easier because you can easily inject a mock repository and on the other hand it makes it explicit that your classes have a dependency like that. You might want to search for the term Dependency Injection.
Simple example:
class Account
{
public Account(IRepository<Account> repository)
{
_Repository = repository;
}
public void ChangeOwner(Owner newOwner)
{
// change ownership
_Repository.Save(this);
}
}
Is it possible to expose the DataContext when extending a class in the DataContext? Consider this:
public partial class SomeClass {
public object SomeExtraProperty {
this.DataContext.ExecuteQuery<T>("{SOME_REALLY_COMPLEX_QUERY_THAT_HAS_TO_BE_IN_RAW_SQL_BECAUSE_LINQ_GENERATES_CRAP_IN_THIS INSTANCE}");
}
}
How can I go about doing this? I have a sloppy version working now, where I pass the DataContext to the view model and from there I pass it to the method I have setup in the partial class. I'd like to avoid the whole DataContext passing around and just have a property that I can reference.
UPDATE FOR #Aaronaught
So, how would I go about writing the code? I know that's a vague question, but from what I've seen online so far, all the tutorials feel like they assume I know where to place the code and how use it, etc.
Say I have a very simple application structured as (in folders):
Controllers
Models
Views
Where do the repository files go? In the Models folder or can I create a "Repositories" folder just for them?
Past that how is the repository aware of the DataContext? Do I have to create a new instance of it in each method of the repository (if so that seems in-efficient... and wouldn't that cause problems with pulling an object out of one instance and using it in a controller that's using a different instance...)?
For example I currently have this setup:
public class BaseController : Controller {
protected DataContext dc = new DataContext();
}
public class XController : BaseController {
// stuff
}
This way I have a "global" DataContext available to all controllers who inherit from BaseController. It is my understanding that that is efficient (I could be wrong...).
In my Models folder I have a "Collections" folder, which really serve as the ViewModels:
public class BaseCollection {
// Common properties for the Master page
}
public class XCollection : BaseCollection {
// X View specific properties
}
So, taking all of this where and how would the repository plug-in? Would it be something like this (using the real objects of my app):
public interface IJobRepository {
public Job GetById(int JobId);
}
public class JobRepository : IJobRepository {
public Job GetById(int JobId) {
using (DataContext dc = new DataContext()) {
return dc.Jobs.Single(j => (j.JobId == JobId));
};
}
}
Also, what's the point of the interface? Is it so other services can hook up to my app? What if I don't plan on having any such capabilities?
Moving on, would it be better to have an abstraction object that collects all the information for the real object? For example an IJob object which would have all of the properties of the Job + the additional properties I may want to add such as the Name? So would the repository change to:
public interface IJobRepository {
public IJob GetById(int JobId);
}
public class JobRepository : IJobRepository {
public IJob GetById(int JobId) {
using (DataContext dc = new DataContext()) {
return dc.Jobs.Single(j => new IJob {
Name = dc.SP(JobId) // of course, the project here is wrong,
// but you get the point...
});
};
}
}
My head is so confused now. I would love to see a tutorial from start to finish, i.e., "File -> New -> Do this -> Do that".
Anyway, #Aaronaught, sorry for slamming such a huge question at you, but you obviously have substantially more knowledge at this than I do, so I want to pick your brain as much as I can.
Honestly, this isn't the kind of scenario that Linq to SQL is designed for. Linq to SQL is essentially a thin veneer over the database; your entity model is supposed to closely mirror your data model, and oftentimes your Linq to SQL "entity model" simply isn't appropriate to use as your domain model (which is the "model" in MVC).
Your controller should be making use of a repository or service of some kind. It should be that object's responsibility to load the specific entities along with any additional data that's necessary for the view model. If you don't have a repository/service, you can embed this logic directly into the controller, but if you do this a lot then you're going to end up with a brittle design that's difficult to maintain - better to start with a good design from the get-go.
Do not try to design your entity classes to reference the DataContext. That's exactly the kind of situation that ORMs such as Linq to SQL attempt to avoid. If your entities are actually aware of the DataContext then they're violating the encapsulation provided by Linq to SQL and leaking the implementation to public callers.
You need to have one class responsible for assembling the view models, and that class should either be aware of the DataContext itself, or various other classes that reference the DataContext. Normally the class in question is, as stated above, a domain repository of some kind that abstracts away all the database access.
P.S. Some people will insist that a repository should exclusively deal with domain objects and not presentation (view) objects, and refer to the latter as services or builders; call it what you like, the principle is essentially the same, a class that wraps your data-access classes and is responsible for loading one specific type of object (view model).
Let's say you're building an auto trading site and need to display information about the domain model (the actual car/listing) as well as some related-but-not-linked information that has to be obtained separately (let's say the price range for that particular model). So you'd have a view model like this:
public class CarViewModel
{
public Car Car { get; set; }
public decimal LowestModelPrice { get; set; }
public decimal HighestModelPrice { get; set; }
}
Your view model builder could be as simple as this:
public class CarViewModelService
{
private readonly CarRepository carRepository;
private readonly PriceService priceService;
public CarViewModelService(CarRepository cr, PriceService ps) { ... }
public CarViewModel GetCarData(int carID)
{
var car = carRepository.GetCar(carID);
decimal lowestPrice = priceService.GetLowestPrice(car.ModelNumber);
decimal highestPrice = priceService.GetHighestPrice(car.ModelNumber);
return new CarViewModel { Car = car, LowestPrice = lowestPrice,
HighestPrice = highestPrice };
}
}
That's it. CarRepository is a repository that wraps your DataContext and loads/saves Cars, and PriceService essentially wraps a bunch of stored procedures set up in the same DataContext.
It may seem like a lot of effort to create all these classes, but once you get into the swing of it, it's really not that time-consuming, and you'll ultimately find it way easier to maintain.
Update: Answers to New Questions
Where do the repository files go? In the Models folder or can I create a "Repositories" folder just for them?
Repositories are part of your model if they are responsible for persisting model classes. If they deal with view models (AKA they are "services" or "view model builders") then they are part of your presentation logic; technically they are somewhere between the Controller and Model, which is why in my MVC apps I normally have both a Model namespace (containing actual domain classes) and a ViewModel namespace (containing presentation classes).
how is the repository aware of the DataContext?
In most instances you're going to want to pass it in through the constructor. This allows you to share the same DataContext instance across multiple repositories, which becomes important when you need to write back a View Model that comprises multiple domain objects.
Also, if you later decide to start using a Dependency Injection (DI) Framework then it can handle all of the dependency resolution automatically (by binding the DataContext as HTTP-request-scoped). Normally your controllers shouldn't be creating DataContext instances, they should actually be injected (again, through the constructor) with the pre-existing individual repositories, but this can get a little complicated without a DI framework in place, so if you don't have one, it's OK (not great) to have your controllers actually go and create these objects.
In my Models folder I have a "Collections" folder, which really serve as the ViewModels
This is wrong. Your View Model is not your Model. View Models belong to the View, which is separate from your Domain Model (which is what the "M" or "Model" refers to). As mentioned above, I would suggest actually creating a ViewModel namespace to avoid bloating the Views namespace.
So, taking all of this where and how would the repository plug-in?
See a few paragraphs above - the repository should be injected with the DataContext and the controller should be injected with the repository. If you're not using a DI framework, you can get away with having your controller create the DataContext and repositories, but try not to cement the latter design too much, you'll want to clean it up later.
Also, what's the point of the interface?
Primarily it's so that you can change your persistence model if need be. Perhaps you decide that Linq to SQL is too data-oriented and you want to switch to something more flexible like Entity Framework or NHibernate. Perhaps you need to implement support for Oracle, mysql, or some other non-Microsoft database. Or, perhaps you fully intend to continue using Linq to SQL, but want to be able to write unit tests for your controllers; the only way to do that is to inject mock/fake repositories into the controllers, and for that to work, they need to be abstract types.
Moving on, would it be better to have an abstraction object that collects all the information for the real object? For example an IJob object which would have all of the properties of the Job + the additional properties I may want to add such as the Name?
This is more or less what I recommended in the first place, although you've done it with a projection which is going to be harder to debug. Better to just call the SP on a separate line of code and combine the results afterward.
Also, you can't use an interface type for your Domain or View Model. Not only is it the wrong metaphor (models represent the immutable laws of your application, they are not supposed to change unless the real-world requirements change), but it's actually not possible; interfaces can't be databound because there's nothing to instantiate when posting.
So yeah, you've sort of got the right idea here, except (a) instead of an IJob it should be your JobViewModel, (b) instead of an IJobRepository it should be a JobViewModelService, and (c) instead of directly instantiating the DataContext it should accept one through the constructor.
Keep in mind that the purpose of all of this is to keep a clean, maintainable design. If you have a 24-hour deadline to meet then you can still get it to work by just shoving all of this logic directly into the controller. Just don't leave it that way for long, otherwise your controllers will (d)evolve into God-Object abominations.
Replace {SOME_REALLY_COMPLEX_QUERY_THAT_HAS_TO_BE_IN_RAW_SQL_BECAUSE_LINQ_GENERATES_CRAP_IN_THIS INSTANCE} with a stored procedure then have Linq to SQL import that function.
You can then call the function directly from the data context, get the results and pass it to the view model.
I would avoid making a property that calls the data context. You should just get the value from a service or repository layer whenever you need it instead of embedding it into one of the objects created by Linq to SQL.