Scott Silvi
Scott Silvi

Reputation: 3109

LINQ where or filter c#

I have a collection being returned by a web service. A property of this collection is "StatusCode" which is a string value that can be anywhere from 0 to 5 (don't ask me why it was set up as a string... I didn't schema this). Initially I was going to use LINQ to filter this, then realized that was stupid (why return 100% of the records when I need 20%) and I parameterized my Stored Proc to do this for me.

In any case, I wrote a LINQ query that worked, but for curiosity sake, I imagine there's a better way to do it:

var wo = from w in workOrders
    where w.StatusCode == "0"
       || w.StatusCode == "1"
       || w.StatusCode == "2"
    select w;

Any suggestions? Correct answer goes to most thorough answer - including either documentation, best practice, etc...

Upvotes: 1

Views: 7671

Answers (5)

Gabriel McAdams
Gabriel McAdams

Reputation: 58293

I recently wrote a blog post about a method using extension methods and params.

By adding this extension method to your code:

public static bool IsIn<T>(this T source, params T[] values)
{
    return values.Contains(source);
}

you can perform your search like this:

var wo = from w in workOrders
    where w.StatusCode.IsIn("0", "1", "2")
    select w;

It works on any type (as long as you create a good equals method). Any value type for sure.

Upvotes: 2

Luk&#225;š Novotn&#253;
Luk&#225;š Novotn&#253;

Reputation: 9052

Your method is ok. I don't believe parsing or lookup collection is neccessary for 3 string values (however it certainly isn't wrong). With parsing I'd be afraid of empty strings or nulls (even tho we know that there should only be strings 0-5).

If you are anticipating filtering like this on more places you should probably create method (or extension) on WorkOrder that would determine current state more expressively like

public static bool IsNotCompleted(this WorkOrder workOrder) 
{
    return workOrder.Status == "0" || workOrder.Status == "1" || workOrder.Status == "2";
}

and then

var wo = from o in workOrders where o.IsNotCompleted() select o;

or (I personally prefer this sytaxe)

var wo = workOrders.Where(o => o.IsNotCompleted());

Using extension to describe state like this will increase readability and it will be much easier to add/remove status codes in future.

Upvotes: 1

Manu
Manu

Reputation: 29163

You could define an IsIn() generic Extension Method:

public static bool IsIn<T>(this T value, params T[] values)
{
    return values.Contains(value);
}

Then you could write your query like this:

var wo = from q in workOrders where w.IsIn("1","2","3") select w;

Upvotes: 1

Ry-
Ry-

Reputation: 225269

var wo = from q in workOrders where int.Parse(w.StatusCode) < 3 select w;

Is a cleaner way to do the LINQ query, at least.

Upvotes: 2

tster
tster

Reputation: 18257

var wo = from w in workOrders 
         where new[]{"0", "1", "2"}.Contains(w.StatusCode)
         select w;

BTW, if you were using an ORM, you could do it in LINQ (like the above) and only pull the 20% from the database ;)

Upvotes: 2

Related Questions