What type of dependency to inject? - dependency-injection

I have a specification that validates codes. It looks like the following:
public ClassificationSpecification : ISpecification<Classification> {
HashSet<string> codes;
// constructor elided
public IsSatisfiedBy(Classification classification) {
return codes.Contains(classification.Code);
}
}
The valid codes come out of a Classification table in a database. My question is, which is the better constructor for dependency injection?
public CodeSpecification(IEnumerable<string> codes) {
this.codes = new HashSet<string>(codes);
}
or
public CodeSpecification(IRepository<Classification> repository) {
this.codes = new HashSet<string>(repository.Select(x => x.Code));
}
And the all important question: why?

Your second constructor does real work (via the repository) and this is a bad idea. See http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/
You need to decide if it's valid to load all the values (pass in the values you need to the constructor), or you want to look them up on each call (pass in the repository in the constructor and store it).

I would use this constructor:
private readonly IRepository<Classification> _repository;
public CodeSpecification(IRepository<Classification> repository)
{
_repository = repository;
}
Then, find the valid codes when your class is actually called upon:
public bool IsSatisfiedBy(Classification classification)
{
var _repository.Any(x => x.Code == classification.Code);
}
This ensures that no real work is done until it is needed, separating your application's initialization from its runtime. It also ensures that you are always working with fresh data in IsSatisfiedBy; caching the values in the constructor introduces a period of time where the codes in the repository might change.
If the number of codes is large, and the repository won't execute the Any efficiently, you may still want to implement caching. It is a good idea to follow the same advice and not cache until the first call to IsSatisfiedBy:
private readonly HashSet<string> _codes;
private readonly object _codesSync = new object();
public bool IsSatisfiedBy(Classification classification)
{
if(_codes == null)
{
lock(_codesSync)
{
if(_codes == null)
{
_codes = new HashSet<string>(_repository.Select(x => x.Code));
}
}
}
return _codes.Contains(classification.Code);
}
Constructors in dependency-injected objects are infrastructure elements; domain logic of any kind should generally be deferred until the object is invoked by another.

Related

Unit of Work pattern implementation

I am creating an application with ASP.NET MVC and Entity framework code first. I am using repository and unit of work pattern with influence of from following link.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Here I have question about the implementation of Unit Of Work in that link unit of work is implemented via directly writing entities in class itself like.
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
}
Do you think that implementation is good enough because every time I add/remove entities I need to change my Unit of work class. I believe that Unit of work should not be dependent on entities. Because in my application based on Client feedback we are going to frequently add/remove entities.
I may sound stupid but let me know your views on that.
The Unit of Work pattern is already implemented in Entity Framework.
The DbContext is your Unit of Work.
Each IDbSet is a Repository.
using (var context = new SchoolContext()) // instantiate our Unit of Work
{
var department = context.Departments.Find(id);
}
There are a few flavors of the UnitOfWorkPattern. The one you are describing is a show everything, there is a hide everything approach as well. In the hide approach the unit of work references the DbContext.SaveChanges() method and nothing else; sounds like what you want.
public YourContext : DbContext, IContext{}
public interface IUnitOfWork{
void Commit();
}
public UnitOfWork : IUnitOfWork{
private readonly IContext _context;
//IOC should always inject the same instance of this, register it accordingly
public UnitOfWork(IContext context){
_context = context;
}
void Commit(){
// try catch the validation exception if you want to return the validations this
// way if your confident you've already validated you can put a void here or
// return the intfrom save changes make sure you handle the disposing properly,
// not going into that here you also may be doing other stuff here, have multiple
// "contexts" to save in a single transaction or we have contextProcessors that
// do stuff based on items in the context
_context.SaveChanges();
}
}
This leaves the issue of how you get your repositories into the classes that need them if you are not taking them from the UnitOfWork. This is best handled by an IOC framework. Again here there are a couple options. Once is to register the UnitOfWork as a single instance per request and have it injected into your custom Repository class.
public interface IRepository<T>
{
IQueryable<T> Records();
//other methods go here
}
public Repository : IRepository<T>
{
private IContext _context;
// same instance of context injected into the unit of work, this why when you Commit
// everything will save, this can get tricky if you start adding Add, Update and stuff
// but EF does have the support needed.
public Repository(IContext context)
{
_context = context;
}
public Records()
{
return _context.Set<T>();
}
}
public class SomeService : ISomeService{
private readonly _myObjectRepository;
public SomeService(IRepository<MyObject> myObjectRepository){
_myObjectRepository = myObjectRepository;
}
}
Personally I consider the IDbSet an sufficient abstraction so I no longer create repositories. In
order to inject the IDbSets from the context though you need to register them as instances that you
extract from the context in your IOC setup. This can be complex and depending on your skills you
could find yourself in the situation where you have to register each IDbSet which I know you are trying to avoid.
What's nice about using the IDbSet is you have access to simple methods like Add and can avoid some of the more complex parts of working with Entity and DbEntity in a generic sense.
public class SomeService : ISomeService {
private readonly _myObjectSet;
// requires specialized IOC configurations because you have to pull this instance from
// the instance of the context, personally don't know how to do this with a single
// registration so this has the same problem as having to add each new repository to the
// unit of work. In this case each new Entity I add to the context requires I add an IOC
// registration for the type.
public SomeService(IDbSet<MyObject> myObjectSet){
_myObjectSet= myObjectSet;
}
}
Try passing the SchoolContext to the GenericRepository:
public GenericRepository<T>
{
private SchoolContext _context;
public GenericRepository(SchoolContext context)
{
_context = context;
}
public Get(int id)
{
return _context.Set<T>().Find(id);
}
}
And use:
using(var context = new SchoolContext())
{
var departmentRepository = new GenericRepository<Department>(context);
var department = departmentRepository.Get(1);
}

Generic save method

In my generic repository I need to write generic Save method which will edit existed or add new entity depending on id.
public void Save<T>(T entity) where T : TEntity, IKeyId
{
if (ObjectSet.Any(r => (r as IKeyId).KeyId == entity.KeyId))
{
Edit(entity);
}
else
{
Add(entity);
}
}
But Linq generate exception when I try do Any( r=> (r as IKeyId)....
The 'TypeAs' expression with an input of type 'MyProg.DAL.Appeal' and a check of type 'Claimstrak.DAL.Interfaces.IKeyId' is not supported. Only entity types and complex types are supported in LINQ to Entities queries.
How to write it correct?
Well, the truth is that you dont need to use the ObjectSet, you can just use DbContext to do this, in a much more easy way.
Bu, i would tell that this is not a good pattern to use, to call a Save() in a repository. I would recomend that you consider the .SaveSession() of the Context only after all was done, this way you can do a lot of things befose making a round trip to te database.
So, you should make a method like this, but not call the SaveChanges(), instead of a Save() method, to a UpdateOrInsert() and them, after all is done you call the .Save()
But i will give the examplefollowing your request (but i dont recommend, i recommend you separate IUnitOfWork from IRepository)
See how the code is very simple:
interface IKeyId
{
int Id { get; set; }
}
DbContext context = new YourContext();
public bool Save<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
return (entity.Id == 0) ? Add<TEntity>(entity) : Edit<TEntity>(entity);
}
public bool Edit<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
var set = context.Set<TEntity>();
set.Attach(entity);
return true;
}
public bool Add<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
var set = context.Set<TEntity>();
set.Add(entity);
return true;
}
I use a similar approach im my repositories, i have changed the T4 (.tt file) that generates the POCO classes from my database to excplicitly implement some interfaces that i have, such as IAuditable, IValidatable and other, so the T4 automaticaly implement those interfaces in the classes.

Entity framework add a where clause to all queries

I am using Entity framework 5 and using repository pattern. Say I got these entities Customer, Files, Images, Tasks, Invoice, User.
Each entity (apart from Customer) has a foreign key of Customer. When a user logs in I store the customerid in session (aps.net mvc). What I want is any CRUD taken on all entities to be limited to the customer who's user is logged in. e.g I can't afford to delete a Task belonging to customer 1 to be deleted by user who is from customer 2.
Is adding an argument of customerid for each method of repositories the best way to achieve this or are there any better/clever ways of doing it?
Tricky to give a definitive answer but you could make it a bit more extensible by implementing higer order functions, like this:
public interface IRepository<T>
{
public T GetBy(Expression<Func<T, bool>> query)
}
public class FileRepository : IRepository<File>
{
public File GetBy(Expression<Func<T, bool>> query)
{
using(var context = new FilesContext())
{
return context.Files.Where(query).FirstOrDefault();
}
}
}
public class SomeController
{
private IRepository<File> _repo;
public SomeController(IRepository<File> repo)
{
_repo = repo;
}
public ActionResult Index()
{
var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);
return View(model);
}
}
This way you can vary the search query when required, rather than tie yourself in to using a hardcoded customer id property. For example, if you wanted to get the File object by the FileID, not the CustomerID, then:
var model = _repo.GetBy(f => f.FileId == someId);
and that's the only part of the code that needs to change.
Some really good info on Higher Order functions and functional programming in C# here: http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
Edit:
You might be able to isolate the "Always use the customer ID when hitting DB" into a repository of it's own, using a decorator style pattern, thus: (massive disclaimer - I haven't tested this, but something along these lines should work)
public class SpecialFileRepo : IRepository<File>
{
private readonly IRepository<File> _baseRepo;
public SpecialFileRepo(IRepository<File> baseRepo)
{
_baseRepo = baseRepo;
}
public SpecialFileRepo() : this(new FileRepository())
{
}
public File GetBy(Expression<Func<File, bool>> query)
{
var parameters = query.Parameters;
var newParam = Expression.Parameter(typeof (File), "f");
var additionalQuery = Expression.AndAlso(query.Body,
Expression.Equal(
Expression.PropertyOrField(newParam, "CustomerId"),
Expression.Constant(HttpContext.Current.Session["customerId"])));
var newQuery = query.Update(additionalQuery, parameters);
return _baseRepo.GetBy(newQuery);
}
}
Then anything that's talking to a repository, as far as it's concerned, it's just a base repository, but this class is sitting in between and always grafting the "customerid = sessionwhatever" expression onto what finally gets passed to the database. And of course, anything that only cares about using the base repository, can still do so.

Automapper + EF4 + ASP.NET MVC - getting 'context disposed' error (I know why, but how to fix it?)

I have this really basic code in a MVC controller action. It maps an Operation model class to a very basic OperationVM view-model class .
public class OperationVM: Operation
{
public CategoryVM CategoryVM { get; set; }
}
I need to load the complete list of categories in order to create a CategoryVM instance.
Here's how I (try to) create a List<OperationVM> to show in the view.
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(
dest => dest.CategoryVM,
opt => opt.MapFrom(
src => CreateCatVM(src.Category, context.Categories)
// trouble here ----------------^^^^^^^
)
);
var opVMs = ops.Select(op => Mapper.Map<Operation, OperationVM>(op))
.ToList();
return View(opVMs);
}
}
All works great first time I hit the page. The problem is, the mapper object is static. So when calling Mapper.CreateMap(), the instance of the current DbContext is saved in the closure given to CreateMap().
The 2nd time I hit the page, the static map is already in place, still using the reference to the initial, now disposed, DbContext.
The exact error is:
The operation cannot be completed because the DbContext has been disposed.
The question is: How can I make AutoMapper always use the current context instead of the initial one?
Is there a way to use an "instance" of automapper instead of the static Mapper class?
If this is possible, is it recommended to re-create the mapping every time? I'm worried about reflection slow-downs.
I read a bit about custom resolvers, but I get a similar problem - How do I get the custom resolver to use the current context?
It is possible, but the setup is a bit complicated. I use this in my projects with help of Ninject for dependency injection.
AutoMapper has concept of TypeConverters. Converters provide a way to implement complex operations required to convert certain types in a separate class. If converting Category to CategoryVM requires a database lookup you can implement that logic in custom TypeConverter class similar to this:
using System;
using AutoMapper;
public class CategoryToCategoryVMConverter :
TypeConverter<Category, CategoryVM>
{
public CategoryToCategoryVMConverter(DbContext context)
{
this.Context = context;
}
private DbContext Context { get; set; }
protected override CategoryVM ConvertCore(Category source)
{
// use this.Context to lookup whatever you need
return CreateCatVM(source, this.Context.Categories);
}
}
You then to configure AutoMapper to use your converter:
Mapper.CreateMap<Category, CategoryVM>().ConvertUsing<CategoryToCategoryVMConverter>();
Here comes the tricky part. AutoMapper will need to create a new instance of our converter every time you map values, and it will need to provide DbContext instance for constructor. In my projects I use Ninject for dependency injection, and it is configured to use the same instance of DbContext while processing a request. This way the same instance of DbContext is injected both in your controller and in your AutoMapper converter. The trivial Ninject configuration would look like this:
Bind<DbContext>().To<SomeContext>().InRequestScope();
You can of course use some sort of factory pattern to get instance of DbContext instead of injecting it in constructors.
Let me know if you have any questions.
I've found a workaround that's not completely hacky.
Basically, I tell AutoMapper to ignore the tricky field and I update it myself.
The updated controller looks like this:
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(dest => dest.CategoryVM, opt => opt.Ignore());
var opVMs = ops.Select(
op => {
var opVM = Mapper.Map<Operation, OperationVM>(op);
opVM.CategoryVM = CreateCatVM(op.Category, context.Categories);
return opVM;
})
.ToList();
return View(opVMs);
}
}
Still curious how this could be done from within AutoMapper...
The answer from #LeffeBrune is perfect. However, I want to have the same behavior, but I don't want to map every property myself. Basically I just wanted to override the "ConstructUsing".
Here is what I came up with.
public static class AutoMapperExtension
{
public static void ConstructUsingService<TSource, TDestination>(this IMappingExpression<TSource, TDestination> mappingExression, Type typeConverterType)
{
mappingExression.ConstructUsing((ResolutionContext ctx) =>
{
var constructor = (IConstructorWithService<TSource, TDestination>)ctx.Options.ServiceCtor.Invoke(typeConverterType);
return constructor.Construct((TSource)ctx.SourceValue);
});
}
}
public class CategoryToCategoryVMConstructor : IConstructorWithService<Category, CategoryVM>
{
private DbContext dbContext;
public DTOSiteToHBTISiteConverter(DbContext dbContext)
{
this.dbContext = dbContext;
}
public CategoryVM Construct(Category category)
{
// Some commands here
if (category.Id > 0)
{
var vmCategory = dbContext.Categories.FirstOrDefault(m => m.Id == category.Id);
if (vmCategory == null)
{
throw new NotAllowedException();
}
return vmCategory;
}
return new CategoryVM();
}
}
// Initialization
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => nInjectKernelForInstance.Get(type));
cfg.CreateMap<Category, CategoryVM>().ConstructUsingService(typeof(CategoryToCategoryVMConstructor));
};

How to remove unit of work functionality from repositories using IOC

I have an application using ASP.NET MVC, Unity, and Linq to SQL.
The unity container registers the type AcmeDataContext which inherits from System.Data.Linq.DataContext, with a LifetimeManager using HttpContext.
There is a controller factory which gets the controller instances using the unity container. I set-up all my dependencies on the constructors, like this:
// Initialize a new instance of the EmployeeController class
public EmployeeController(IEmployeeService service)
// Initializes a new instance of the EmployeeService class
public EmployeeService(IEmployeeRepository repository) : IEmployeeService
// Initialize a new instance of the EmployeeRepository class
public EmployeeRepository(AcmeDataContext dataContext) : IEmployeeRepository
Whenever a constructor is needed, the unity container resolves a connection, which is used to resolve a data context, then a repository, then a service, and finally the controller.
The issue is that IEmployeeRepository exposes the SubmitChanges method, since the service classes DO NOT have a DataContext reference.
I have been told that the unit of work should be managed from outside the repositories, so it would seem I ought to remove SubmitChanges from my repositories. Why is that?
If this is true, does this mean that I have to declare an IUnitOfWork interface and make every service class dependent upon it? How else can I allow my service classes to manage the unit of work?
You shouldn't try to supply the AcmeDataContext itself to the EmployeeRepository. I would even turn the whole thing around:
Define a factory that allows creating a new unit of work for the Acme domain:
Create an abstract AcmeUnitOfWork that abstracts away LINQ to SQL.
Create a concrete factory that can allows creating new LINQ to SQL unit of works.
Register that concrete factory in your DI configuration.
Implement an InMemoryAcmeUnitOfWork for unit testing.
Optionally implement convenient extension methods for common operations on your IQueryable<T> repositories.
UPDATE: I wrote a blog post on this subject: Faking your LINQ provider.
Below is a step-by-step with examples:
WARNING: This will be a loooong post.
Step 1: Defining the factory:
public interface IAcmeUnitOfWorkFactory
{
AcmeUnitOfWork CreateNew();
}
Creating a factory is important, because the DataContext implement IDisposable so you want to have ownership over the instance. While some frameworks allow you to dispose objects when not needed anymore, factories make this very explicit.
Step 2: Creating an abstract unit of work for the Acme domain:
public abstract class AcmeUnitOfWork : IDisposable
{
public IQueryable<Employee> Employees
{
[DebuggerStepThrough]
get { return this.GetRepository<Employee>(); }
}
public IQueryable<Order> Orders
{
[DebuggerStepThrough]
get { return this.GetRepository<Order>(); }
}
public abstract void Insert(object entity);
public abstract void Delete(object entity);
public abstract void SubmitChanges();
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract IQueryable<T> GetRepository<T>()
where T : class;
protected virtual void Dispose(bool disposing) { }
}
There are some interesting things to note about this abstract class. The Unit of Work controls and creates the Repositories. A repository is basically something that implements IQueryable<T>. The repository implements properties that return a specific repository. This prevents users from calling uow.GetRepository<Employee>() and this creates a model that is very close to what you are already doing with LINQ to SQL or Entity Framework.
The unit of work implements Insert and Delete operations. In LINQ to SQL these operations are placed on the Table<T> classes, but when you try to implement it this way it will prevent you from abstracting LINQ to SQL away.
Step 3. Create a concrete factory:
public class LinqToSqlAcmeUnitOfWorkFactory : IAcmeUnitOfWorkFactory
{
private static readonly MappingSource Mapping =
new AttributeMappingSource();
public string AcmeConnectionString { get; set; }
public AcmeUnitOfWork CreateNew()
{
var context = new DataContext(this.AcmeConnectionString, Mapping);
return new LinqToSqlAcmeUnitOfWork(context);
}
}
The factory created a LinqToSqlAcmeUnitOfWork based on the AcmeUnitOfWork base class:
internal sealed class LinqToSqlAcmeUnitOfWork : AcmeUnitOfWork
{
private readonly DataContext db;
public LinqToSqlAcmeUnitOfWork(DataContext db) { this.db = db; }
public override void Insert(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).InsertOnSubmit(entity);
}
public override void Delete(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).DeleteOnSubmit(entity);
}
public override void SubmitChanges();
{
this.db.SubmitChanges();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
where TEntity : class
{
return this.db.GetTable<TEntity>();
}
protected override void Dispose(bool disposing) { this.db.Dispose(); }
}
Step 4: Register that concrete factory in your DI configuration.
You know self best how to register the IAcmeUnitOfWorkFactory interface to return an instance of the LinqToSqlAcmeUnitOfWorkFactory, but it would look something like this:
container.RegisterSingle<IAcmeUnitOfWorkFactory>(
new LinqToSqlAcmeUnitOfWorkFactory()
{
AcmeConnectionString =
AppSettings.ConnectionStrings["ACME"].ConnectionString
});
Now you can change the dependencies on the EmployeeService to use the IAcmeUnitOfWorkFactory:
public class EmployeeService : IEmployeeService
{
public EmployeeService(IAcmeUnitOfWorkFactory contextFactory) { ... }
public Employee[] GetAll()
{
using (var context = this.contextFactory.CreateNew())
{
// This just works like a real L2S DataObject.
return context.Employees.ToArray();
}
}
}
Note that you could even remove the IEmployeeService interface and let the controller use the EmployeeService directly. You don't need this interface for unit testing, because you can replace the unit of work during testing preventing the EmployeeService from accessing the database. This will probably also save you a lot of DI configuration, because most DI frameworks know how to instantiate a concrete class.
Step 5: Implement an InMemoryAcmeUnitOfWork for unit testing.
All these abstractions are there for a reason. Unit testing. Now let's create a AcmeUnitOfWork for unit testing purposes:
public class InMemoryAcmeUnitOfWork: AcmeUnitOfWork, IAcmeUnitOfWorkFactory
{
private readonly List<object> committed = new List<object>();
private readonly List<object> uncommittedInserts = new List<object>();
private readonly List<object> uncommittedDeletes = new List<object>();
// This is a dirty trick. This UoW is also it's own factory.
// This makes writing unit tests easier.
AcmeUnitOfWork IAcmeUnitOfWorkFactory.CreateNew() { return this; }
// Get a list with all committed objects of the requested type.
public IEnumerable<TEntity> Committed<TEntity>() where TEntity : class
{
return this.committed.OfType<TEntity>();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
{
// Only return committed objects. Same behavior as L2S and EF.
return this.committed.OfType<TEntity>().AsQueryable();
}
// Directly add an object to the 'database'. Useful during test setup.
public void AddCommitted(object entity)
{
this.committed.Add(entity);
}
public override void Insert(object entity)
{
this.uncommittedInserts.Add(entity);
}
public override void Delete(object entity)
{
if (!this.committed.Contains(entity))
Assert.Fail("Entity does not exist.");
this.uncommittedDeletes.Add(entity);
}
public override void SubmitChanges()
{
this.committed.AddRange(this.uncommittedInserts);
this.uncommittedInserts.Clear();
this.committed.RemoveAll(
e => this.uncommittedDeletes.Contains(e));
this.uncommittedDeletes.Clear();
}
protected override void Dispose(bool disposing)
{
}
}
You can use this class in your unit tests. For instance:
[TestMethod]
public void ControllerTest1()
{
// Arrange
var context = new InMemoryAcmeUnitOfWork();
var controller = new CreateValidController(context);
context.AddCommitted(new Employee()
{
Id = 6,
Name = ".NET Junkie"
});
// Act
controller.DoSomething();
// Assert
Assert.IsTrue(ExpectSomething);
}
private static EmployeeController CreateValidController(
IAcmeUnitOfWorkFactory factory)
{
return new EmployeeController(return new EmployeeService(factory));
}
Step 6: Optionally implement convenient extension methods:
Repositories are expected to have convenient methods such as GetById or GetByLastName. Of course IQueryable<T> is a generic interface and does not contains such methods. We could clutter our code with calls like context.Employees.Single(e => e.Id == employeeId), but that's really ugly. The perfect solution to this problem is: extension methods:
// Place this class in the same namespace as your LINQ to SQL entities.
public static class AcmeRepositoryExtensions
{
public static Employee GetById(this IQueryable<Employee> repository,int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
public static Order GetById(this IQueryable<Order> repository, int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
// This method allows reporting more descriptive error messages.
[DebuggerStepThrough]
private static TEntity Single<TEntity, TKey>(IQueryable<TEntity> query,
TKey key) where TEntity : class
{
try
{
return query.Single();
}
catch (Exception ex)
{
throw new InvalidOperationException("There was an error " +
"getting a single element of type " + typeof(TEntity)
.FullName + " with key '" + key + "'. " + ex.Message, ex);
}
}
}
With these extension methods in place, it allows you to call those GetById and other methods from your code:
var employee = context.Employees.GetById(employeeId);
What the nicest thing is about this code (I use it in production) is that -once in place- it saves you from writing a lot of code for unit testing. You will find yourself adding methods to the AcmeRepositoryExtensions class and properties to the AcmeUnitOfWork class when new entities are added to the system, but you don't need to create new repository classes for production or testing.
This model has of course some shortcomes. The most important perhaps is that LINQ to SQL isn't abstract away completely, because you still use the LINQ to SQL generated entities. Those entity contain EntitySet<T> properties which are specific to LINQ to SQL. I haven't found them to be in the way of proper unit testing, so for me it's not a problem. If you want you can always use POCO objects with LINQ to SQL.
Another shortcome is that complicated LINQ queries can succeed in test but fail in production, because of limitations (or bugs) in the query provider (especially the EF 3.5 query provider sucks). When you do not use this model, you are probably writing custom repository classes that are completely replaced by unit test versions and you will still have the problem of not being able to test queries to your database in unit tests. For this you will need integration tests, wrapped by a transaction.
A last shortcome of this design is the use of Insert and Delete methods on the Unit of Work. While moving them to the repository would force you to have a design with an specific class IRepository<T> : IQueryable<T> interface, it prevents you from other errors. In the solution I use myself I also have InsertAll(IEnumerable) and DeleteAll(IEnumerable) methods. It is however easy to mistype this and write something like context.Delete(context.Messages) (note the use of Delete instead of DeleteAll). This would compile fine, because Delete accepts an object. A design with delete operations on the repository would prevent such statement from compiling, because the repositories are typed.
UPDATE: I wrote a blog post on this subject that describes this solution in even more detail: Faking your LINQ provider.
I hope this helps.
If combining unit of work and repository patterns, some people advocate that UoW should be managed outside of repository so that you could create two repositories (say, CustomerRepository and OrderRepository) and pass them the same UoW instance ensuring that all the changes to the DB will be done atomically when you finally call UoW.Complete().
In a mature DDD solution however, there should not be need for both UoW and a repository. This is because is such a solution aggregate boundaries are defined is such a way, that there is no need of atomic changes involving more than one repository.
Does this answer your question?

Resources