HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Factoring WHERE clauses in IQueryable

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
factoringwhereiqueryableclauses

Problem

I recovered some spaghetti code and I have to refactor it. I do not want a method with over 200 lines, for me it is not object oriented programming. I am trying to ponder on the question and would like to have your suggestions.

```
private static IQueryable BuildTradeQuery(IRepositoryFactory repository, SearchCriteria SearchCriteria)
{
var query = GetTrades(repository);
var dteToday = DateTime.Today;

if (SearchCriteria.RemitterId != null)
{
query = query.Where(x => x.RemitterId == (Remitter) SearchCriteria.RemitterId);
}
if (!string.IsNullOrWhiteSpace(SearchCriteria.TradeReference))
{
query = query.Search(x => x.TradeReference, SearchCriteria.TradeReference);
}
if (!string.IsNullOrWhiteSpace(SearchCriteria.Sicovam))
{
query = query.Search(x => x.Sicovam, SearchCriteria.Sicovam);
}
if (SearchCriteria.AssetClassId != null)
{
query = query.Where(x => x.AssetClassId == (AssetClass) SearchCriteria.AssetClassId);
}
if (!string.IsNullOrWhiteSpace(SearchCriteria.Desk))
{
query = query.Where(x => x.Desk == SearchCriteria.Desk);
}
if (SearchCriteria.SubGroupUpiId != null)
{
query = query.Where(x => x.SubGroupUpiId == (SubGroupUpi) SearchCriteria.SubGroupUpiId);
}
if (SearchCriteria.IsBuy != null)
{
query = query.Where(x => x.IsBuy == SearchCriteria.IsBuy);
}
if (SearchCriteria.FromTradeDate != null)
{
query = query.Where(x => x.TradeDate >= SearchCriteria.FromTradeDate);
}
if (SearchCriteria.ToTradeDate != null)
{
query = query.Where(x => x.TradeDate x.StartDate >= SearchCriteria.FromStartDate);
}
if (SearchCriteria.ToStartDate != null)
{
query = query.Where(x => x.StartDate x.EndDate >= SearchCriteria.From

Solution

Sometimes if I don't need anything OO (Object-Oriented) or it's a part of a bad code anyway I usually refactor something like this into that:

The simplest or maybe quick&dirty way to group all the ifs into some structure that is easier to maintain is to create an array of Funcs that take the search-criteria and the current query as a parameter and return an updated query if the search-criteria is met or an unchanged query if not.

Each element of the array is such an anonymous function evaluating only a single condition and updating the query if necessary.

var queries = new Func, IQueryable>[]
{
    (sc, q) => sc.EventReference != null ? q.Search(x = > x.EventReference, sc.EventReference) : q,
    (sc, q) => !sc.PendingEvent ? q.Where(x = > x.EventStatusId != EventStatus.Pending) : q,
    ...
};


Finally you run all functions in a loop and pass the required parameters.

foreach(var queryFunc in queries)
{
    query = queryFunc(searchCriteria, query);
}


For more information see:

  • Func Delegate



  • foreach, in (C# Reference)



  • var (C# Reference)



  • ?: Operator (C# Reference)



  • Lambda Expressions (C# Programming Guide)



  • Arrays (C# Programming Guide)



  • Semicolons in C#

Code Snippets

var queries = new Func<SearchCriteria, IQueryable<T>, IQueryable<T>>[]
{
    (sc, q) => sc.EventReference != null ? q.Search(x = > x.EventReference, sc.EventReference) : q,
    (sc, q) => !sc.PendingEvent ? q.Where(x = > x.EventStatusId != EventStatus.Pending) : q,
    ...
};
foreach(var queryFunc in queries)
{
    query = queryFunc(searchCriteria, query);
}

Context

StackExchange Code Review Q#143094, answer score: 6

Revisions (0)

No revisions yet.