1

I am trying to refactor a class which extract from a DB some objects of type QuerySuggest. Two queries are made on the objects returned from the DB, using Linq.

It's evident that the two queries are almost identical, the only difference is that in the former I have an additional condition : " && e.UserId == request.UserId".

This seems to me as a code smell, and I would like to refactor it, but I'm not sure on how to proceed.

this is the sample of code I need to refactor:

IRepository<QuerySuggest> repository = _repositoryManager.GetRepository<QuerySuggest>(_repositoryType);

        //entitiesByUser contains all the query suggest by the user
        var entitiesByUser = repository.Query(c => c.Where(e => e.IdWebsite == request.WebSiteId &&
                                                        e.FulltextFree != null &&
                                                        e.DataOra >= (System.DateTime.Today.AddDays(-60).Date) &&
                                                        e.UserId == request.UserId)
                                                .GroupBy(g => g.FulltextFree)
                                                .Select(n => new { FulltextFree = n.Key, HowMany = n.Count() })
                                                .Where(w => w.HowMany >= request.HowMany)
                                                .OrderBy(o => o.HowMany))
                                                .ToList();
        //entitiesByUser contains all the query suggest not from user
        var nonUserEntities = repository.Query(c => c.Where(e => e.IdWebsite == request.WebSiteId &&
                                                        e.FulltextFree != null &&
                                                        e.DataOra >= (System.DateTime.Today.AddDays(-60).Date))
                                                .GroupBy(g => g.FulltextFree)
                                                .Select(n => new { FulltextFree = n.Key, HowMany = n.Count() })
                                                .Where(w => w.HowMany >= request.HowMany)
                                                .OrderBy(o => o.HowMany))
                                                .ToList();
davideAlbertini
  • 93
  • 2
  • 11

2 Answers2

1

I believe this should be one way to do it:

IList<QuerySuggest> QuerySuggestions(
    RequestType request, 
    bool filterByUser = false,
    bool excludeUser = false)
{
    IRepository<QuerySuggest> repository = 
        _repositoryManager.GetRepository<QuerySuggest>(_repositoryType);

    var entities = repository
        .Query(c => c.Where(e => 
            e.IdWebsite == request.WebSiteId &&
            e.FulltextFree != null &&
            e.DataOra >= (System.DateTime.Today.AddDays(-60).Date) &&
            (!filterByUser || e.UserId == request.UserId) &&
            (!excludeUser || e.UserId != request.UserId)
        )
        .GroupBy(g => g.FulltextFree)
        .Select(n => new { FulltextFree = n.Key, HowMany = n.Count() })
        .Where(w => w.HowMany >= request.HowMany)
        .OrderBy(o => o.HowMany))
        .ToList();

    return entities;
}

IList<QuerySuggest> QuerySuggestionsByUser(RequestType request)
{
    return QuerySuggestions(request, filterByUser: true);
}

IList<QuerySuggest> QuerySuggestionsAnyUser(RequestType request)
{
    return QuerySuggestions(request);
}

IList<QuerySuggest> QuerySuggestionsOtherUsers(RequestType request)
{
    return QuerySuggestions(request, excludeUser: true);
}
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • What if I need to have `e.UserId == request.UserId` in one case and `e.UserId != request.UserId` in the other ? The logic expression is no longer valid, I tried many different expressions without success – davideAlbertini Feb 15 '17 at 09:10
  • @davideAlbertini Made an update above. Please give that a try. – JLRishe Feb 15 '17 at 09:31
0

You could write a method that combines predicates. @Jon Skeet has provided two such methods here:

Combine Multiple Predicates

You should be able to use them something like this:

Predicate<YourType> a = e => e.IdWebsite == request.WebSiteId &&
                                            e.FulltextFree != null &&
                                            e.DataOra >= (System.DateTime.Today.AddDays(-60).Date);

Predicate<YourType> b = e => e.UserId == request.UserId;

var entitiesByUser = repository.Query(c => c.Where(Helpers.And(a, b)));
Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88