Beau D'Amore
Beau D'Amore

Reputation: 3404

LINQ: is there a way to conditionally modify expression?

I need to search in my context and child objects for a string. The main objects are 'Property' and 'BayOption' with a property having 1-many BayOptions.

The tricky part is, almost each parameter for both objects has an 'XXXXOverride' bool and a complimentary 'XXXXOverrideValue'. I need to check if the 'Override' bool is true and if so, use the 'OverrideValue', not the standard value. As in:

(LINQ pseudo-code):

if (x.NameOverride){
x.NameOverrideValue.Contains(searchString);
}
else{
x.Name == searchString;
}

My current LINQ does not account for the overrides and looks like this:

 List<Property> stringResults = db.Properties
                .Where(x => x.Address.Contains(searchString)
                    || x.Address.Contains(searchString)
                    || x.Address2.Contains(searchString)
                    || x.City.Contains(searchString)
                    || x.Description.Contains(searchString)
                    || x.GrossLeasableArea.ToString().Contains(searchString)
                    || x.MaxContiguous.ToString().Contains(searchString)
                    || x.MinDivisible.ToString().Contains(searchString)
                    || x.Name.Contains(searchString)
                    || x.SquareFootage.ToString().Contains(searchString)
                    || x.WebsiteURL.Contains(searchString)
                    || x.Zip.Contains(searchString)
                    // tags
                    || x.Tags.Any(f => f.TagName.Contains(searchString))
                    // bayoptions
                    || x.BayOptions.Any(g => g.Description.Contains(searchString))
                    ).ToList();

Scope/FYI: Answering this question will help me figure out another problem I'm having with 'SiteVisibilityFlags'... A flagged Enum where I have to check if it .HasFlag() for this site. (these properties can be shown/hidden depending on what site we determine to show them on, so I have to check the 'SiteVisibilityFlag' AND check if it has an 'override'(bool+override string) and use the override value if the bool is true... One more scope item, this data comes from an CRM/ERP system in a daily one-way sync but can be overridden by salespeople. So, I have to check both places.)

Upvotes: 0

Views: 96

Answers (2)

David
David

Reputation: 218960

Something like this?:

|| (x.AddressOverride ? x.AddressOverrideValue.Contains(searchString) : x.Address.Equals(searchString))
|| (x.Address2Override ? x.Address2OverrideValue.Contains(searchString) : x.Address2.Equals(searchString))
//...

Disclaimer: Untested free-hand code ahead...

You might be able to reduce code duplication by making a generic Expression<Func<>> that the expression tree can use, maybe something like this:

public static Expression<Func<string, bool, string, string, bool>> ContainsValue = 
    (originalValue, isOverride, overrideValue, searchString) =>
    isOverride ? overrideValue.Contains(searchString) : originalValue.Equals(searchString);

This can be compiled and used in an expression tree so it should still evaluate against the data source instead of materializing everything into memory first. The usage might look like this:

|| Property.ContainsValue.Compile()(x.Address, x.AddressOverride, x.AddressOverrideValue, searchString)
|| Property.ContainsValue.Compile()(x.Address2, x.Address2Override, x.Address2OverrideValue, searchString)

It consolidates the logic a little bit, but doesn't necessarily do much for readability or reduction of code. So it's a judgement call on your part.

Upvotes: 1

Shantanu Gupta
Shantanu Gupta

Reputation: 21108

Creating a computed property can help

e.g.

public class Foo
{
  public string MyProp{get;set;}
 public string SerarchParam{get;set;}
 public bool SearchResult{
           get 
               {
                 return this.MyProp && this.MyPro.Contains(SearchParam);
               }
   }
}

To use this class

You need to initialize SearchParam property first before using SearchResult.

Upvotes: 0

Related Questions