LINQ - WHERE X IN (…)

30 11 2007

I couldn’t figure out a way to perform the equivalent of WHERE Column1 IN ('A', 'B', 'C') in LINQ, where (’A', ‘B’, ‘C’) would represent an IEnumerable<T> where T is the type of Column1. So I thought it was an excellent time to write an extension method that would generate a dynamic expression tree that would add AND (Column1 == "A" OR Column1 = "B" OR ...) to the LINQ query. So I wrote the following code:

public static IQueryable<TSource> WhereIn<TSource, TKey> (
        this IQueryable<TSource> source1,
        Expression<Func<TSource, TKey>> keySelector,
        IEnumerable<TKey> source2) {
    if (null == source1)
        throw new ArgumentNullException ("source1");
    if (null == keySelector)
        throw new ArgumentNullException ("keySelector");
    if (null == source2)
        throw new ArgumentNullException ("source2");
    Expression where = null;
    foreach (TKey value in source2) {
        Expression equal = Expression.Equal (
                    keySelector.Body,
                    Expression.Constant (value, typeof (TKey))
                    );
        if (null == where)
            where = equal;
        else
            where = Expression.OrElse (where, equal);
    }
    return source1.Where<TSource> (
        Expression.Lambda<Func<TSource, bool>> (
            where, keySelector.Parameters));
}

An example of the usage:

var q = (from u in db.Users
    where u.LastLogin > new DateTime (2007, 5, 1)
    orderby u.LastLogin descending
    select new { u.FirstName, u.LastName, u.UserName, u.LastLogin }
    ).WhereIn (u => u.UserName, new string[] { "A", "B", "C" });

A day later, I found the right way that will actually generate “WHERE X IN (…)” in LINQ to SQL thanks to Mark Blomsma.



SqlMetal.exe crashes when a column name in the result set is [ ].

28 11 2007

The last message to be written to the console was: “Error : Index was outside the bounds of the array.”.

To reproduce this bug, create this stored procedure and run SqlMetal against it:
CREATE PROCEDURE [dbo].[ThisProcedureWillCauseSqlMetalToCrash] AS
BEGIN
SET NOCOUNT ON;
SELECT 1 [A], 2 [ ], 3 [C]
END

Applies to:

  • Visual Studio 2008 RTM
  • Microsoft Windows SDK v6.0A

Please rate and validate this problem at the MSDN Microsoft Product Feedback Center so Microsoft responds with a solution or workaround.