tags:

views:

131

answers:

5

I have the following method:

public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
{
    return db.Profiles.Where(p => p.CountryFrom.CountryName.Equals(CountryFrom,
        StringComparison.OrdinalIgnoreCase));
}

What is the best way to write the where clause that would filter all the possible combinations of input parameters in one statement:

BOTH CountryFrom and CountryLoc = null

Only CountryFrom null

Only CountryLoc null

BOTH CountryFrom and CountryLoc are not null.

Soon .. I would need to filter out profiles by Age, Gender, Profession .. you name it.

I am trying to find a way to write it efficiently in C#. I know how to do it in a clean manner in TSQL. I wish I knew the way. Thanks for all the responses so far.

+2  A: 

A good old binary XNOR operation will do the trick here:

db.Profiles.Where(p => !(p.CountryFrom == null ^ p.CountryTo == null))

It's effectively equating two booleans, though to me it's more direct, less convoluted even, than writing ((p.CountryFrom == null) == (p.CountryTo == null))!

Noldorin
A: 

I wouldn't call this elegant:

public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
{
    return db.Profiles.Where(p =>
        {
            p.ContryFrom != null &&
            p.CountryFrom.CountryName != null &&
            p.CountryFrom.CountryName.Equals(CountryFrom, StringComparison.OrdinalIgnoreCase)
        });
}
Jamie Ide
A: 

Hi, I would use this simple LINQ syntax...

BOTH CountryFrom and CountryLoc = null

var result = from db.Profiles select p
             where (p.CountryFrom == null) && (p.CountryLoc == null)
             select p

Only CountryFrom null

var result = from db.Profiles select p
             where (p.CountryFrom == null) && (p.CountryLoc != null)
             select p

Only CountryLoc null

var result = from db.Profiles select p
             where (p.CountryFrom != null) && (p.CountryLoc == null)
             select p

BOTH CountryFrom and CountryLoc are not null.

var result = from db.Profiles select p
             where (p.CountryFrom != null) && (p.CountryLoc != null)
             select p

Hope it helps ;-)

Tomas
I think you misunderstood the question. He wants the results all returned together by a single query.
Noldorin
A: 

I'm in favor of not trying to cram too much logic into a linq expression. Why not contain your comparison logic in a separate function like this?

EDIT: I provided an example implementation of the MatchesCountry function.

class Example
{
    public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
    {
        return db.Profiles.Where(p => p.MatchesCountry(CountryFrom, CountryLoc));
    }
}

public static class ProfileExtensions
{
    public static bool MatchesCountry(this Profile profile, string CountryFrom, string CountryLoc)
    {
        // NOTE: Your comparison logic goes here.  Below is an example implementation

        // if the CountryFrom parameter was specified and matches the profile's CountryName property
        if(!string.IsNullOrEmpty(CountryFrom) && string.Equals(profile.CountryName, CountryFrom, StringComparison.OrdinalIgnoreCase))
            return true; // then a match is found

        // if the CountryLoc parameter was specified and matches the profile's CountryCode property
        if (!string.IsNullOrEmpty(CountryLoc) && string.Equals(profile.CountryCode, CountryLoc, StringComparison.OrdinalIgnoreCase))
            return true; // then a match is found

        // otherwise, no match was found
        return false;
    }
}
Dr. Wily's Apprentice
can you please provide me some sample code on what will go inside the separate function.
dotnet-practitioner
This code may not match both CountryFrom and CountryLoc at the same time.. : - (
dotnet-practitioner
Well, if you need to handle all possible combinations of CountryFrom and CountryLoc being null or not null, then you just need to write the logic of MatchesCountry to suit your needs. My answer was intended to provide a way to write a clean/understandable where clause. Having the "country matching" logic separated into its own function also allows it to be reused elsewhere, in case that's helpful. By separating the matching logic into its own function, you can write your logic however is easiest for you without trying to cram it into a lambda expression.
Dr. Wily's Apprentice
A: 

I may be missing something, but as written, your combination of operators will either let all values through or no values through depending on whether you use || or && to combine them together.

Steve Mitcham