1

I have implemented Repository + UnitOfWork pattern in my DAL, I am using Entity Framework (EF) to connect to the DB.

The service layer calls UnitOfWork to get a specific repository, and then interacts with repository methods using EF Entities.

The returned EF Entities from Repository to Service, are then mapped into Models (POCO objects, only properties, no functionality), and then these POCOs are passed to the Controller that called the Service in the first place.

All looks good so far, except when:

I need to use "Joins" in my LINQ queries in my repository, and return a custom object to the service layer.

The problem here is, that I was making sure, my repository only takes in and sends out EF Entities. But if I need to use join, I'll be populating a custom Model object, and will then be passing back Model instead of EF Entity.

To tackle the above problem, I was thinking that I should change my repository such that, it takes IN entities (e.g. for ADD, DELETE, UPDATE), but returns back Models (for select methods etc).

This means, my service layer will be creating Entities from Models, and then passing entities to the Repository, for any ADD, UPDATE, DELETE

And my Repository will be creating Models from Entities when returning results of a select LINQ queries.

Any thoughts if I'll be in a greater problem later if I choose to go with the above design?

If the above design is not a good solution, any other advise?

6
  • I believe Repositories job should be to just Add, Update, delete etc for a single entity. In this case you might prefer using a generic Repository where your service layer would handle all the querying, retrieving and passing on entities to and from your web and Dal layer. The service layer(I call it buinsess layer) should hold on to the logic that retrieves data from multiple repositories and passes it back to the web layer as Model, and vice versa. Commented Mar 31, 2014 at 9:38
  • I am using generic repository for ADD,UPDATE,DELETE,FINDBYID and FINDALL ... as you suggested I thought of using repository only for this, and then insert into my models data from multiple repositories as i needed. But this will mean, I'll be making unnecessary calls to DB. For example, if I need to get data from TableA and TableB, and populate my ModelAB, and my query has 50 results from TableA, i'll doing a foreach loop for TableA's results to get a corresponding record from TableB, and then populate my ModelAB. This will mean calling DB 50 times extra in a loop to get TableB records. Commented Mar 31, 2014 at 9:45
  • If you are using generic repository you can create a method with a signature Like following Get(System.Linq.Expressions.Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "") and return an IQueryable object. After that you can join any tables that you want and retrieve the data with single DB hit. Commented Mar 31, 2014 at 9:55
  • Well, your repository "should" return IQueryable, and your service do something on these IQueryable and return "enumerated" datas. So your repository will return an IQueryable<A> (no call to db), and IQueryable<B>(no call to db) and your service layer will make a join on these two Queryables and return an IList<joinedAb> => 1 call to db. No ? Commented Mar 31, 2014 at 10:03
  • Thanks Nilesh/Raphael, I thought of that. I only have two reservations with this approach, First: my query logic will be in the Business Layer (not a very big deal, I can live with that) ... but the second: what if i want to query TableA and TableB again to generate ModelAB in another Business Layer method, which does something else, but needs this information as well. In that case, I'll be duplicating the exact same query again? For example if you want to get a custom UserModel based on UserRegistrationNumber ... you may need this kind of query in multiple Business Logic methods ... Commented Mar 31, 2014 at 10:05

1 Answer 1

1

You're using the wrong repository approach, the anti-pattern. The Repository makes sens only as a decoupling pattern i.e you want tot decouple the Business Layer(BL) from the Persistence Layer(PL).

This means, your Bl (and services) don't know about EF or any other ORM. This means that your repository interface only know about what BL knows,that is the business objects. Your repository should NEVER expose EF, IQueryable or other PL detail.

First of all you need UoW pattern ONLY when updating a model, never just for queries. Then, when you're asking the repository for something, you tell it what you want and the repository will use EF, create queries, joins etc and maps the query results to the POCO the repository returns . So the mapping from EF entities to domain objects is done inside the repository.

Actually, ALL work related to the database via EF (or any other ORM) is done inside the repository. The BL just gets their object in the final form. That's the whole point of the repository.

What you're doing now is wrong, because you are doing repository's work at the BL level, violating the Separation of Concerns principle. The proper use of repository is like I wrote above.

P.S: In case you wonder, the generic repository is an anti pattern, stay away from it. As a side note, a generic repository interface is not the same thing as a generic repository.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.