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

Était-ce utile?

La 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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top