Home > other >  How to simplify this LINQ WHERE query?
How to simplify this LINQ WHERE query?

Time:09-04

I'm trying to select several rows from a table but would like the selection to stop if the first where clause comes back with results. Basically if there are results with language then I don't need to query for DevLanguage or FallbackLanguage, is this possible in a single query with || operator or with some other LINQ magic?

        var languageStrings = _presentationContext.LocalizationStrings
            .Where(x => x.Namespace.Namespace == @namespace &&
                        x.Namespace.Language == language);

        var devStrings = _presentationContext.LocalizationStrings
            .Where(x => x.Namespace.Namespace == @namespace &&
                        x.Namespace.Language == Constants.DevLanguage);

        var fallbackStrings = _presentationContext.LocalizationStrings
            .Where(x => x.Namespace.Namespace == @namespace &&
                        x.Namespace.Language == Constants.FallbackLanguage);

        var localizationStrings = languageStrings.Any() ? languageStrings : devStrings.Any() ? devStrings : fallbackStrings.Any() ? fallbackStrings

CodePudding user response:

While there are probably more downsides to the code below than I know of, it's a one-liner (if you ignore the temp variable declaration) and only executes the LINQ queries if the previous one failed to return any results.

IEnumerable<dynamic> temp;
var localizationStrings =
        (temp = _presentationContext.LocalizationStrings.Where(x => 
                    x.Namespace.Namespace == @namespace && 
                    x.Namespace.Language == language)).Any() ? temp :
        (temp = _presentationContext.LocalizationStrings.Where(x => 
                    x.Namespace.Namespace == @namespace &&
                    x.Namespace.Language == Constants.DevLanguage)).Any() ? temp :
        (temp = _presentationContext.LocalizationStrings.Where(x =>
                    x.Namespace.Namespace == @namespace &&
                    x.Namespace.Language == Constants.FallbackLanguage)).Any() ? temp :
        Enumerable.Empty<string>();

One reason why I would either pick your original code or search for a different method is because assigning values in a chain like this is not performance friendly.

CodePudding user response:

I would put the common part of these queries into a separate query.

var query = _presentationContext.LocalizationStrings.Where(x => x.Namespace.Namespace == @namespace);

var languageStrings = query.Where(x => x.Namespace.Language == language);
var devStrings = query.Where(x => x.Namespace.Language == Constants.DevLanguage);
var fallbackStrings = query.Where(x => x.Namespace.Language == Constants.FallbackLanguage);

The SQL is generated the same.


If you need to minimize the number of roundtrips then the code may look like this.

var query = _presentationContext.LocalizationStrings.Where(x => x.Namespace.Namespace == @namespace);

var languageStrings = query.Where(x => x.Namespace.Language == language);
var devStrings = query.Where(x => x.Namespace.Language == Constants.DevLanguage);
var fallbackStrings = query.Where(x => x.Namespace.Language == Constants.FallbackLanguage);

IQueryable<Localization> localizationStrings = null;

if (languageStrings.Any())
    localizationStrings = languageStrings;
else if (devStrings.Any())
    localizationStrings = devStrings;
else if (fallbackStrings.Any())
    localizationStrings = fallbackStrings;
  • Related