Question

I have a generic repository with a Query Method that returns IQueryable. In my calling code I can then do something like this

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

However, I would then be unable to test the calling code ( as far as I know ). So I'm trying to do the following

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);
    }
}

So the first call to Fetch works but the call to repositor.ThenFetch takes an INhFetchRequest query but returns an INhFetchRequest. So I can't then use the FetchedResult to call the ThenFetch a second time.

I think this is the problem. My brain is pretty unraveled at this point. If anyone can help let me know and I can try and give more or better information.

Now I know I can do it using statics however, my goal here is to be able to mock the calls to Fetch.

Thanks,

Raif

Was it helpful?

Solution

Alrighty, my feeble brain has finally grasped the solution. After a boring as hell commute I realized that the problem was with the generics being in on the object level rather then the method level. The following is my solution. I may blog on said matter in which case later I will include the link

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();
    }
}

usage would be as follows

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

I do find that the generic declarations are a bit verbose, but it freakin works and I'm leaving it at that for now. Any suggestions, of course, would be welcome.

Raif

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top