Как мне обернуть Linq2NHibernate .Fetch и .ThenFetch внутри моего абстрактного репозитория?

Я использую общий репозиторий, который предоставляет IQueryable следующим образом:

public IQueryable<T> AllEntities
{
    get
    {
        return session.Query<T>();
    }
}

Я могу запросить вот так:

var results =
    (from e in repository.AllEntities
     where e.SomeProperty == "some value"
     select e).ToList();

Однако, если T имеет родительскую и прародительскую сущность, и я хочу загрузить их с нетерпением, я должен сделать это:

var results =
    (from e in repository.AllEntities
     where e.SomeProperty == "some value"
     select e)
    .Fetch(x => x.Parent)
    .ThenFetch(x => x.Grandparent)
    .ToList();

Это работает, но .Fetch и .ThenFetch оба являются специальными методами расширения Linq2Nhibernate, что вызывает две проблемы:

  1. Я должен включить с использованием NHibernate.Linq; оператор в верхней части моего файла. Однако в тот момент, когда я выполняю этот запрос, он не должен зависеть от реализации.

  2. Когда я пытаюсь выполнить модульное тестирование, методы .Fetch и .ThenFetch терпят неудачу при выполнении против IQueryable , который предоставляет мой фиктивный репозиторий.

Как я могу обернуть их внутри моего интерфейса IRepository или внутри каких-то общих методов расширения?

Обновление:

Пока что все, что я придумал, - это добавьте это в интерфейс моего репозитория:

IQueryable<T> EagerLoadParent<U>(IQueryable<T> query, 
    Expression<Func<T, U>> parentExpression);
IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
    Expression<Func<T, U>> parentExpression, 
    Expression<Func<U, V>> grandparentExpression);

... и это в мою реализацию репозитория NHibernate:

public IQueryable<T> EagerLoadParent<U>(IQueryable<T> query,
    Expression<Func<T, U>> parentExpression)
{
    return query
        .Fetch(parentExpression);
}

public IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
    Expression<Func<T, U>> parentExpression, 
    Expression<Func<U, V>> grandparentExpression)
{
    return query
        .Fetch(parentExpression)
        .ThenFetch(grandparentExpression);
}

Потребитель этого API теперь делает следующее:

var query =
    (from e in repository.AllEntities
     where e.SomeProperty == "some value"
     select e);
var results = repository
    .EagerLoadParent(query, e => e.Parent, p => p.Grandparent)
    .ToList();

Но здесь отсутствует красивый синтаксис метода расширения, который я бы предпочел. Я ищу что-то более близкое к синтаксису .Fetch и .ThenFetch .

15
задан Scott Whitlock 26 January 2011 в 21:21
поделиться