用于Nhibernate的Fluent Wrapper获取ThenFetch

时间:2013-06-17 14:13:18

标签: nhibernate generics repository fetch fluent-interface

我有一个带有Query Method的通用存储库,它返回IQueryable。在我的调用代码中,我可以做这样的事情

_repository.Query<MyClass>(x=>x.EntityId == 1).Fetch(x=>x.MyClassChild).ToList()

然而,我将无法测试调用代码(据我所知)。所以我试图做以下事情

public class Repository : IRepository
{
....
    public FetchedResult<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector)
    {
        INhFetchRequest<TQueried, TRelated> nhFetchRequest = query.ThenFetch(relatedObjectSelector);
        return new FetchedResult<TQueried, TRelated>(this, nhFetchRequest);
    }

    public FetchedResult<TOriginating, TRelated> Fetch<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector)
    {
        INhFetchRequest<TOriginating, TRelated> nhFetchRequest = query.Fetch(relatedObjectSelector);
        return new FetchedResult<TOriginating, TRelated>(this, nhFetchRequest);
    }
}

-

public class FetchedResult<TQueried, TRelated>
{
    private readonly IRepository _repository;
    private readonly INhFetchRequest<TQueried, TRelated> _query;

    public FetchedResult(IRepository repository, INhFetchRequest<TQueried, TRelated> query)
    {
        _repository = repository;
        _query = query;
    }

    public FetchedResult<TQueried, TRelated> ThenFetch<TFetch>(Expression<Func<TFetch,TRelated>> relatedObjectSelector)
    {
        return _repository.ThenFetch(_query, relatedObjectSelector);
    }
}

因此,对Fetch的第一次调用有效,但对repositor.ThenFetch的调用采用INhFetchRequest查询但返回INhFetchRequest。所以我不能再使用FetchedResult再次调用ThenFetch。

我认为这是问题所在。在这一点上,我的大脑已经很难解开了。如果有人可以帮助我告诉我,我可以尝试提供更多或更好的信息。

现在我知道我可以使用静态来实现它,但我的目标是能够模拟对Fetch的调用。

谢谢,

RAIF

1 个答案:

答案 0 :(得分:0)

好吧,我虚弱的大脑终于抓住了解决方案。在通勤无聊之后,我意识到问题在于泛型是在对象级别而不是方法级别。以下是我的解决方案。我可以在上述问题上发表博客,在这种情况下我将包含链接

public class Repository : IRepository
{
....
    public FetchQuery QueryFetch<ENTITY>(Expression<Func<ENTITY, bool>> where = null) where ENTITY : Entity
    {
        var query = _unitOfWork.CurrentSession.Query<ENTITY>();
        var queryable = where == null ? query : query.Where(where);
        return new FetchQuery(this, queryable);
    }

    public FetchedResult ThenFetch<TQueried, TFetch, TRelated>(INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector)
    {
        INhFetchRequest<TQueried, TRelated> nhFetchRequest = query.ThenFetch(relatedObjectSelector);
        return new FetchedResult(this, nhFetchRequest);
    }

    public FetchedResult ThenFetchMany<TQueried, TFetch, TRelated>(INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector)
    {
        INhFetchRequest<TQueried, IEnumerable<TRelated>> nhFetchRequest = query.ThenFetch(relatedObjectSelector);
        return new FetchedResult(this, nhFetchRequest);
    }

    public FetchedResult Fetch<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector)
    {
        INhFetchRequest<TOriginating, TRelated> nhFetchRequest = query.Fetch(relatedObjectSelector);
        return new FetchedResult(this, nhFetchRequest);
    }

    public FetchedResult FetchMany<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector)
    {
        INhFetchRequest<TOriginating, TRelated> nhFetchRequest = query.FetchMany(relatedObjectSelector);
        return new FetchedResult(this, nhFetchRequest);
    }
}

public class FetchedResult
{
    private readonly IRepository _repository;
    private object _query;
    public FetchedResult(IRepository repository, object query)
    {
        _repository = repository;
        _query = query;
    }

    public FetchedResult ThenFetch<TQueried, TFetch, TRelated>(Expression<Func<TFetch, TRelated>> relatedObjectSelector)
    {
        return _repository.ThenFetch((INhFetchRequest<TQueried, TFetch>)_query, relatedObjectSelector);
    }

    public FetchedResult ThenFetchMany<TQueried, TFetch, TRelated>(Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector)
    {
        return _repository.ThenFetchMany((INhFetchRequest<TQueried, TFetch>)_query, relatedObjectSelector);
    }

    public List<TOriginating> ToList<TOriginating>()
    {
        return ((IQueryable<TOriginating>)_query).ToList();
    }
}

public class FetchQuery
{
    private readonly IRepository _repository;
    private readonly object _query;

    public FetchQuery(IRepository repository, object query)
    {
        _repository = repository;
        _query = query;
    }

    public FetchedResult Fetch<TOriginating, TRelated>(Expression<Func<TOriginating, TRelated>> relatedObjectSelector)
    {
        return _repository.Fetch((IQueryable<TOriginating>)_query, relatedObjectSelector);
    }

    public FetchedResult FetchMany<TOriginating, TRelated>(Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector)
    {
        return _repository.FetchMany((IQueryable<TOriginating>)_query, relatedObjectSelector);
    }

    public List<TOriginating> ToList<TOriginating>()
    {
        return ((IQueryable<TOriginating>) _query).ToList();
    }
}

用法如下

_repository.QueryFetch<InternetProfile>(x => x.CompanyId == Id ).FetchMany<InternetProfile, SiteProperty>(x => x.SiteProperties).ToList<InternetProfile>();

我确实发现通用声明有点冗长,但它很有效,我现在就把它留在那里。当然,任何建议都会受到欢迎。

RAIF