I have a nice clean domain layer in my app that was developed in a DDD fashion. The database was not considered at all when developing the domain. Property names make sense, aren’t in ALL CAPS, and are relevant to my application.
Today, I am implementing a repository to pull from an existing EF DbContext. The DbContext was developed to (basically) match a poorly-designed Oracle database.
Ideally, I would like to implement a repository like this:
public interface IRepository {
IQueryable<T> Find<T>(Expression<Func<T, bool>> query) where T : IMyDomainEntity;
}
T is my domain entity. But, inside my Find method in my repository, I have to…
-
Somehow convert the expression to work with the DbContext
I am not sure how to do this yet.
-
Query the DbContext
Once the expression is ‘mapped’, this is simple
-
Somehow map to my domain object
I’m sure I can use AutoMapper or implement my own mapper.
-
Return an IQueryable having not made a trip to the database yet.
Not sure this is possible after all the meddling done in #’s 1 – 3
So, how has this problem been solved in the past? Are there any reusable patterns here?
Well, you’re on the right track already, just implement what your say you want 🙂
1.You’re passing an expression into your find method so, just use that expression in your Where clause
2.You just need to get the correct DbSet from your DbContext to query against, DbContext has a method to get the DbContext of a given type, use that and you can query like
3.If your domain objects are not the ones mapped by EF to the database, you’ll need to customize your mapping against what’s in your DB in your DbContext class (no need for automapper for that), so you would have something like this in your DbContext class
To map from the table DB_USERS in the DB to the class User, having different names for the fields, etc. here’s an article on that
http://www.codeproject.com/Articles/165720/Using-the-Code-First-Model-Configuration-Classes
You could also map the properties to the correct table columns using attributes if you don’t want/can’t change your DbContext class
http://msdn.microsoft.com/en-us/data/gg193958
Or you can have a different set of entities that are mapped to your DB and use automapper to translate them into your domain objects, but you lose no. 4 bellos since you’ll need to materialize the query to automap it to your domain model.
4.No need to do anything special, EF takes care of the that
UPDATE: Solution without having access to the DbContext (not fully generic version but works)
The idea is to create the mapping part of the repository for each domain class, so all gets binded correctly. Continueing with the
Userdomain model andDBUsertable model:Then you would have an abstract Repository and an a concrete repository per domain class that implements the basic GetAll query mapped:
now to use it you will just call the find or get all on the repository…
It is not fully generic since you will need to pass a repository for each domain class you need to use, but it may be an acceptable compromise
Hope this helps