Я создал проект для тестирования NHibernate 3+ и Entity Framework 4.1, поместив его в репозиторий, сделав его очень тестируемым с использованием интерфейсов и т. Д.
Я не хочу показывать ORM вне репозиториев (я даже не выставляю IQueryables). Все должно быть обработано в этом слое, и до тех пор, пока я не попытался обработать извлечение абстрактным способом, все было хорошо.
В Microsoft добавление активной загрузки использует либо магические строки (yuck), либо выражения Linq (yay) в функции Include. Их синтаксис выглядит примерно так:
IQueryableThing.Include(o => o.Person);
IQueryableThing.Include(o => o.Company.Contact);
IQueryableThing.Include(o => o.Orders.Select(p => p.LineItem.Cost);
Первый просто загрузит ассоциированного человека. (Родитель)
Второй загрузит ассоциированную компанию и контакт каждой компании. (родитель и дедушка).
Третий будет загружать все связанные заказы, позиции и затраты для каждого заказа.
Это довольно приятная реализация.
NHibernate использует немного другой подход. Они по-прежнему используют выражения Linq, но более активно используют методы расширения (свободный подход).
IQueryableThing.Fetch(o => o.Person);
IQueryableThing.Fetch(o => o.Company).ThenFetch(o => o.Contact);
IQueryableThing.FetchMany(o => o.Orders).ThenFetch(p => p.LineItem).ThenFetch(q => q.Cost);
(я не уверен, что в третьей строке правильный синтаксис)
Я могу инкапсулировать список выражений в отдельный класс, а затем применить эти выражения к IQueryable внутри этого класса. Поэтому мне нужно стандартизировать синтаксис выражений Microsoft, а затем преобразовать его в синтаксис NHibernate, обходя дерево выражений и перестраивая каждое выражение.
Это действительно сложная часть. Я должен поддерживать определенный порядок операций, чтобы вызвать правильную функцию для IQueryable (должен начинаться либо с Fetch, либо с FetchMany, каждый из которых должен быть «ThenFetch» или «ThenFetchMany»), что мешает мне использовать в классе ExpressionVisitor.
Edit:
Наконец, я создал анализатор выражений, который будет принимать любой уровень вложенности свойств, коллекций и селекций в коллекциях и создавать массив выражений. К сожалению, встроенные методы расширений Fetch не принимают LambdaExpression в качестве параметра.
Часть, на которой я застрял в настоящее время , не может использовать встроенные определения Fetch из nHibernate. Похоже, мне, возможно, придется напрямую нажимать на функции библиотеки Remotion или регистрировать собственные методы расширения, которые удовлетворят их анализатор.
Фанки.