patterncsharpMinor
Factoring WHERE clauses in IQueryable
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
```
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
Each element of the array is such an anonymous function evaluating only a single condition and updating the query if necessary.
Finally you run all functions in a loop and pass the required parameters.
For more information see:
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.