2012-03-02 2 views
1

Я создал общий репозиторий с некоторыми методами поверх EF Codefirst, который отлично работает. Get метод выглядит следующим образом (это включает для одного уровня)Как создать общий репозиторий с 'deep include'?

public virtual IEnumerable<T> Get(
     Expression<Func<T, bool>> filter = null, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, 
     string includeProperties = "") 
{ 

     IQueryable<T> query = _dDbSet; 

     if (filter != null) 
      query = query.Where(filter); 

     query = includeProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty)); 

     return orderBy != null ? orderBy(query).ToList() : query.ToList(); 
    } 

Но я натыкаюсь на проблему, когда мне нужно общий репозиторий возвращать «глубже» включают

пример: объект Отель имеют отношение к списку номеров, и каждая комната имеет отношение к человеку.

Я хочу, чтобы мой метод возвращал объект отеля со списком номеров с человеком из этих номеров.

Как я могу решить эту проблему с помощью GenericRepository?

Я не хочу использовать решение:

var hotel = _hotelRepository.Context.Hotels.Where(p => p.HotelId == HotelId).Include(p => p.RoomList.Select(b => b.Person)).First(); 

в моем bussinesclass, потому что я хочу, чтобы отделить из доступа к данным в genericRepository и иметь возможность издеваться способом в моем тестовом проекте.

Есть ли хорошее решение для этого, или мне нужно использовать контекст с помощью Select, как указано выше?

Спасибо!

ответ

4

Я чувствую запах Inner-Platform Effect. Вы пытаетесь сделать свой общий репозиторий, чтобы все, что делает EF. Почему бы не использовать EF (или любой другой ORM, который вы используете) напрямую?

Лично я отбросил свои собственные хранилища некоторое время назад. Я инкапсулирую многоразовые запросы, используя ORM непосредственно в классах «report». Для более простых одноразовых запросов я использую ORM напрямую. Когда я пишу классы отчетов или прямые запросы, я знаю, что включать/извлекать с нетерпением и т. Д. И использовать инструменты, предлагаемые ORM.

Помните: ваш ORM уже - это репозиторий, нет необходимости обертывать его (IMO).

См http://ayende.com/blog/3955/repository-is-the-new-singleton

+0

Да, это я вижу, и я стараюсь держать хранилище как малые, как Возможное. Но все больше и больше я вижу, что моему репозиторию может понадобиться новый метод, чтобы сделать выборку с «более глубоким» включением. Я мог бы подумать об этом с неправильного угла. У меня нет проблем с ORM, так же как и с предложением Select в моем внутреннем вопросе. Но его труднее издеваться над всеми различными context.hotel.where (h => h.id == и т. Д.), Чем GenericRepository.Get(). – TommyKey

+0

Я понимаю, что репозитории легко насмехаются и, таким образом, отлично подходят для тестирования. Но даже без репозиториев у вас есть опции: 1) настроить встроенную базу данных (SQLite) для тестирования. Да, это не будет 100% изолированных тестов. 2) Переместите часть, в которую вы вызываете ORM, в виртуальный метод, создайте производный класс, переопределите эти методы и введите тестовые значения (в основном применяйте шаблон шаблона шаблона] (http://en.wikipedia.org/wiki/ Template_method_pattern)). 3) Для сложных запросов изолируйте их в отдельном классе, для которого вы вводите подделки/mocks/stubs в свои тесты. –

+0

+1 для этого термина _Inner-Platform Effect_. –

Смежные вопросы