Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type to return when querying multiple entities in Repository layer?

I have the following layers involved in this question:

  • Service Layer (Using IoC to call Repository)
  • Domain Model (POCO / Domain Entities, defined repository Interfaces)
  • Repository Layer (EF .edmx and implemented repositories)

A lot of times it's really straight forward: Repository layer queries database via Entity Framework and returns IList<SomeDomainEntity> to caller which was Service Layer. The type returned is a type defined in the Domain Model.

The problem I'm running into is when I need to query across POCOs A,B, and C and get data from all to be returned. Since I don't handle any logic in the repository I need to return this data back to the Service layer to be processed (either directly or more likely by calling some logic on domain model). However I don't have a single type anymore from the results of the repository query to return to the caller.

An anonymous type of course handles this in examples I see, but since I'm not processing that logic from returned data directly in the Repository and it needs to be returned, I need a physical type to return. Here are some solutions I thought of but not sure I like any:

  1. Create a new domain entity in Domain Model that essentially is a composition of all the data I queried, so this new single type may be returned. This seems wrong to create abritrary types to satisy query needs.
  2. Make the service layer call the individual repositories on A,B,C entities separately and then deal with the data from each returned object. This seems like a lot of extra work.
  3. Create a ViewModel to return. This seems out of place to me as well. I leverage ViewModel classes heavily between my service layer and UI layers, but never seen them leveraged for return from the repository.

I can't be the only one querying across multiple entities to get a conglomeration of data back that needs to be added to a type and returned to the caller. What is a common practice or standard way of going about this to solve my problem?

Thanks!

like image 860
atconway Avatar asked Feb 20 '13 17:02

atconway


2 Answers

If those entities are related and you query all of them in one place then you should try to find an aggregate root of them in your domain model or if it doesn't exist yet you should introduce a new one, as you said in the first option. This is not wrong until it makes sense. It should model a domain concept and you probably have one because you created that repository method.

If those entities are not related (well, probably related in some way, but not that tightly as above) and you just want to get them in one go then you should handle that in the service layer where you can use multiple repositories and compose a result object.

You probably heard of the concept of navigation properties and eager loading but I write it here because it may be another answer to your question (I don't see your domain model)

I wouldn't go with your third suggestion (create viewmodels in the repository) because it breaks the separations.

like image 92
Peter Porfy Avatar answered Sep 29 '22 17:09

Peter Porfy


Different entities can relate to each other whithout one of them being an aggregate root. Services are used to these kind of queries. I usually do something like this:

public class MyService
{
    IEnumerable<UserWithMessages> Find()
    {
        var messages = _messageRepository.FindAll();
        var userIds = _messages.Select(x => x.UserId).Distinct().ToArry();
        var users = _userRepository.Find(userIds);
        return users.Select(x => new UserWithMessages(x, messages.Where(x => x.UserId == x.Id));
    }
}

It's just two DB queries which can utilize indexes in the DB. So It should be pretty fast.

like image 26
jgauffin Avatar answered Sep 29 '22 16:09

jgauffin