###Rewind.
Rewind.
###Enter EF.
Enter EF.
###Rewind.
###Enter EF.
Rewind.
Enter EF.
You mock IDbSet<T>
mock IDbSet<T>
and the interface your DbContext
is implementing. Simple as that.
You mock IDbSet<T>
and the interface your DbContext
is implementing. Simple as that.
You mock IDbSet<T>
and the interface your DbContext
is implementing. Simple as that.
The idea behind abstracting the database stuff, is that you need to be able to test/run your business code without actually hitting the database. I use something like this:
public interface IUnitOfWork
{
void Commit();
IDbSet<T> Set<T>();
}
The IDbSet<T>
can be mocked (you Setup
the return value of Set<T>()
), and by coding against this IUnitOfWork
, you have an abstraction you can use to mock your DbContext
:
public class MyContext : DbContext, IUnitOfWork
{
public void Commit()
{
SaveChanges();
}
public IDbSet<Foobar> Foobars { get; set; }
// ...
}
The "repositories" become an implementation detail, they're just for EF to pick up: your code is working against an IDbSet<TEntity>
- does that not look just about exactly like a generic repository?
So does this mean EF should be tightly coupled to my domain layer [...]?
If you're coding against IUnitOfWork
, you have a loose enough coupling to test everything you need to test, without hitting a database. Yes, you're using an interface (IDbSet<T>
) that is essentially some EntityFrameworkRepository<TEntity>
... but to swap for a NHibernateRepository<TEntity>
you'd have to reimplement all the seam-level code anyway, leaked or not; the business-layer code only ever needs to see/use an IEnumerable<TEntity>
, and the TEntity
in question. By reusing your entity classes, and only ever exposing a group of them as an IEnumerable<TEntity>
, you pretty much shield your business code from even noticing that it's no longer Entity Framework providing them with this TEntity
.
The idea behind abstracting the database stuff, is that you need to be able to test/run your business code without actually hitting the database. I use something like this:
public interface IUnitOfWork
{
void Commit();
IDbSet<T> Set<T>();
}
The IDbSet<T>
can be mocked (you Setup
the return value of Set<T>()
), and by coding against this IUnitOfWork
, you have an abstraction you can use to mock your DbContext
:
public class MyContext : DbContext, IUnitOfWork
{
public void Commit()
{
SaveChanges();
}
public IDbSet<Foobar> Foobars { get; set; }
// ...
}
The "repositories" become an implementation detail, they're just for EF to pick up: your code is working against an IDbSet<TEntity>
- does that not look just about exactly like a generic repository?
So does this mean EF should be tightly coupled to my domain layer [...]?
If you're coding against IUnitOfWork
, you have a loose enough coupling to test everything you need to test, without hitting a database. Yes, you're using an interface (IDbSet<T>
) that is essentially some EntityFrameworkRepository<TEntity>
... but to swap for a NHibernateRepository<TEntity>
you'd have to reimplement all the seam-level code anyway, leaked or not; the business-layer code only ever needs to see/use an IEnumerable<TEntity>
, and the TEntity
in question. By reusing your entity classes, and only ever exposing a group of them as an IEnumerable<TEntity>
, you pretty much shield your business code from even noticing that it's no longer Entity Framework providing them with this TEntity
.