Skip to content

Instantly share code, notes, and snippets.

@Dillie-O
Last active December 17, 2015 22:09
Show Gist options
  • Save Dillie-O/5679454 to your computer and use it in GitHub Desktop.
Save Dillie-O/5679454 to your computer and use it in GitHub Desktop.
Refactored BuildObjectQuery method
public static ObjectQuery<T> BuildObjectQuery<T>
(ObjectQuery<T> query, NameValueCollection parameters,
Dictionary<string, SearchParameter> searchCriteria)
{
var results = query;
// If there are parameters in our collection, build a where clause
// using the search criteria dictionary. Otherwise the method ends
// and the query remains the same.
if (parameters.Count > 0)
{
var whereClause = new StringBuilder();
var isFirstParameter = true;
// Before processing parameters, check for from/to pairings for
// range queries. If a pairing exists, replace with the
// appropriate range key.
var keys = parameters.AllKeys.ToList();
foreach (var key in keys)
{
// Since parameters can be removed midloop, check for value
// before processing
if (!parameters.AllKeys.Contains(key)) continue;
// Test for from and to index values for simplified processing
var indexFrom = key.IndexOf("From", StringComparison.Ordinal);
var indexTo = key.IndexOf("To", StringComparison.Ordinal);
// Skip key if it is not a from/to parameter.
if (indexFrom <= 0 && indexTo <= 0) continue;
// Process parameter based on what name was found (from/to).
var keyPrefix = indexFrom > 0 ? key.Substring(0, indexFrom) : key.Substring(0, indexTo);
var fromKey = keyPrefix + "From";
var toKey = keyPrefix + "To";
// Make sure that there is a From and a To key to process.
if (!parameters.AllKeys.Contains(fromKey) || !parameters.AllKeys.Contains(toKey)) continue;
// Add range parameter, remove corresponding from/to
// parameters, and remove paired from/to key to prevent
// duplicate processing.
var rangeValue = parameters[fromKey] + "|" + parameters[toKey];
parameters.Add(keyPrefix + "Range", rangeValue);
parameters.Remove(keyPrefix + "From");
parameters.Remove(keyPrefix + "To");
}
for (var i = 0; i < parameters.Count; i++)
{
// Build Where clause
var itemKey = parameters.GetKey(i);
var itemValue = parameters.Get(i);
var itemClause = string.Empty;
SearchParameter criteria;
ObjectParameter queryParameter;
// Make sure search key exists
if (!searchCriteria.TryGetValue(itemKey, out criteria))
{
throw new Exception("Search Criteria Does Not Exist: " + itemKey);
}
if (!isFirstParameter)
{
whereClause.Append(" AND ");
}
else
{
isFirstParameter = false;
}
// Null item values avoid any kind of parameter processing and
// change the where clause slightly before appending to the query.
if (itemValue == "null")
{
itemClause = criteria.WhereClause.Replace(" = {0}", " IS NULL");
whereClause.Append(itemClause);
}
else
{
// Most search criteria can simply be appended to the query. Some
// are multi-value selectors and need to be processed accordingly.
if (!criteria.AllowsMultipleValues)
{
// Most parameters are single values, but if there is a range
// parameter we must split the values up.
if (!criteria.IsRangeSearch)
{
itemClause = String.Format(criteria.WhereClause, "@" + criteria.VariableName);
whereClause.Append(itemClause);
// Add parameter to query
var valueText = itemValue;
if (criteria.IsWildcardSearch)
{
valueText = "%" + valueText + "%";
}
// Most of the time we use the value specified. However, null values
// require the DBNull value.
queryParameter = new ObjectParameter
(criteria.VariableName, criteria.ParameterType)
{ Value = valueText };
query.Parameters.Add(queryParameter);
}
else
{
// Use same variable name, simply append "From/To" to its name.
itemClause = String.Format(criteria.WhereClause, "@" + criteria.VariableName + "From",
"@" + criteria.VariableName + "To");
whereClause.Append(itemClause);
// Add parameter to query
var splitValue = itemValue.Split('|');
if (criteria.IsWildcardSearch)
{
splitValue[0] = "%" + splitValue[0] + "%";
splitValue[1] = "%" + splitValue[1] + "%";
}
// Most of the time we use the value specified. However, null values
// require the DBNull value.
queryParameter = new ObjectParameter
(criteria.VariableName + "From", criteria.ParameterType)
{ Value = splitValue[0] };
query.Parameters.Add(queryParameter);
// Most of the time we use the value specified. However, null values
// require the DBNull value.
queryParameter = new ObjectParameter
(criteria.VariableName + "To", criteria.ParameterType)
{ Value = splitValue[1] };
query.Parameters.Add(queryParameter);
}
}
else
{
// Parameter contains multiple values, which are split into a
// nested OR clause.
var values = itemValue.Split(',').Select(Convert.ToString).ToList();
if (values.Count > 0)
{
for (var j = 0; j <= values.Count - 1; j++)
{
// Jump to next item in the loop if empty.
if (String.IsNullOrEmpty(values[j])) continue;
if (j != 0)
{
whereClause.Append(" OR ");
}
else if (values.Count > 1)
{
whereClause.Append(" (");
}
itemClause = String.Format(criteria.WhereClause, "@" + criteria.VariableName + j);
whereClause.Append(itemClause);
// Add parameter to query
var valueText = values[j];
if (criteria.IsWildcardSearch)
{
valueText = "%" + valueText + "%";
}
// Add parameter to query
queryParameter = new ObjectParameter
(criteria.VariableName + j, criteria.ParameterType)
{ Value = valueText };
query.Parameters.Add(queryParameter);
}
if (values.Count > 1)
{
whereClause.Append(") ");
}
}
}
}
}
// Append where clause to results.
results = query.Where(whereClause.ToString());
}
return results;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment