Posted By: SecretSoftware | May 25th, 2007 @ 5:14 PM
page 1 of 1
Comments: 18 | Views: 6366
SecretSoftware
SecretSoftware
Code to live, but Live to code.
HI
    Is there an equivalent CASE Operator in LINQ?

As in @S = CASE....

If not, is it going to be implemented?
C# and VB already have an equivalent operator to the SQL CASE operator. C# has the ternary/conditional operator which is the 'x ? y : z' operator.   VB has the IIF operator, 'IIF(x,y,z)'



odujosh
odujosh
Need Microsoft SUX now!

Do a Group By Query.

Foreach over the set of groups pass the group through a standard switch statement that handles a ienumerable<T> where T is the type of the object you are grouping.

odujosh
odujosh
Need Microsoft SUX now!

While I have never used Case since usually don't handle items in batch. There is no V1 plans that I have seen for doing Case. Although there are several work arounds for this.

The main reason I think is every domain would have to implement the feature. I am very sure this feature is an extreme edge case. There are plenty of ways in SQL to get around not using a CASE as I am sure you know.

When thinking about LINQ and why did they not add X. Ask yourself does this make sense in LINQ to XML, LINQ to Amazon, or LINQ to your domain.

Re: lack of Case or Conditional  statements in LINQ

I have been using XQuery and XSLT2.0 for some very complex transformations and recently tried to translate these into LINQ. But the lack of Case or If statements forced me into some very ugly constructs.

For me this limitation is a complete show-stopper for LINQ. Anyone similarly frustrated will find that XQuery1.0 is much easier to learn and much more versatile for XML querying.

The Saxonica implementation of XQuery is especially good: it has extensions for indexing that give massive performance enhancements.

JChung2006 wrote:


You can use lambda expressions in lieu of CASE syntax.

IEnumerable values = Enumerable.Range(1, 3);
Func switchFunc = x =>
{
    switch (x)
    {
        case 1: return "ONE";
        case 2: return "TWO";
        default: return "***";
    }
};
var switchedValues = values.Select(value => switchFunc.Invoke(value));
foreach (string value in switchedValues)
{
    Console.WriteLine(value);
}

A POF (Plain Ol' Function) would also suffice.



++ Big Smile

You can use lambda expressions in lieu of CASE syntax.

IEnumerable<int> values = Enumerable.Range(1, 3);
Func<int, string> switchFunc = x =>
{
    switch (x)
    {
        case 1: return "ONE";
        case 2: return "TWO";
        default: return "***";
    }
};
var switchedValues = values.Select(value => switchFunc.Invoke(value));
foreach (string value in switchedValues)
{
    Console.WriteLine(value);
}

A POF (Plain Ol' Function) would also suffice.

Thanks for your suggestion. This is an option for simple cases but an extremely complicated option if you want to branch to more code within the query.

Until Microsoft get this deficiency fixed, LINQ cannot be a serious alternative to XQuery or XSLT2.0.
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
edmund wrote:
Thanks for your suggestion. This is an option for simple cases but an extremely complicated option if you want to branch to more code within the query.

Until Microsoft get this deficiency fixed, LINQ cannot be a serious alternative to XQuery or XSLT2.0.


If you're having much more complex switches over your database that is suggestive that you should be splitting your query into smaller sub-queries (or a stored procedure) or should be refactoring your database into something more logical.
edmund wrote:
Until Microsoft get this deficiency fixed, LINQ cannot be a serious alternative to XQuery or XSLT2.0.

Sorry, but I disagree.  Being able to invoke an arbitrary function as part of your LINQ expression makes it rather, well, expressive.  You could even write an LINQ to XSLT or LINQ to XQuery provider if you absolutely must have your angle brackets though.

It's possible to effectively write CASE statements in LINQ using the ternary operator like this:

var qry = from c in db.Customers
   select new {
      CustomerName = c.CustomerId == 1 ? "Joe" :
                                    c.CustomerId ==2 ? "Bob" : 
                                    c.CustomerId == 3 ? "Tom" :
                                    "Unknown"
   };

This will actually generate a SQL CASE statement like:

SELECT
  CASE
      WHEN c.CustomerId = 1 THEN 'Joe'
      WHEN c.CustomerId = 2 THEN 'Bob'
      WHEN c.CustomerId = 3 THEN 'Tom'
      ELSE 'Unknown'
  END CustomerName
FROM
  Customers c

I wrote up a blog post on it here:
http://lancefisher.net/blog/archive/2008/05/07/linq-to-sql---case-statements.aspx

Sampy
Sampy
This will be the sixth time we have destroyed it and we have become exceedingly efficient at it
Maybe this is just the examples I'm seeing but this looks like you should be joining to a look up table. You can do that in the DB or after you get the items back to the client.
Sampy wrote:
Maybe this is just the examples I'm seeing but this looks like you should be joining to a look up table. You can do that in the DB or after you get the items back to the client.


Right, I knew that was coming.  This is just an example of how to generate the CASE statement, not the best practice in this situation.  It is useful in other situations where you might not have a lookup table, or a lookup table doesn't make sense.

Suppose you wanted to show different text based on some numerical range:

var qry = from o in orders
                select new {
                   Message = o.TotalAmt < 10 ? "Cheapo" :
                                     10 <= o.TotalAmt && o.TotalAmt < 100 ? "Moderate Spender":
                                     "Big Spender" //for orders $100 or more
                }

That kind of problem is not easily solved with a lookup table.  Also, there are times when you might not be able to add lookup tables, and you just have to deal with the database as it is.  CASE is a good tool to have.
Sampy
Sampy
This will be the sixth time we have destroyed it and we have become exceedingly efficient at it
You can always perform the join with LINQ to Objects after you have retrieved the items from the database. You can even use an array of anonymous types to do so.

I don't want to try and say "CASE is useless! You don't need it!" but rather that I don't think the lack of CASE as an obvious part of LINQ to SQL (or just LINQ in general) is a huge problem. If you really need it, you can use the trinary operator trick mentioned above but there are other ways to achieve the same effect.
In VB, use Microsoft.VisualBasic.Switch function; LINQ will translate into CASE statement.
page 1 of 1
Comments: 18 | Views: 6366
Microsoft Communities