0

Possible Duplicate:
'Contains()' workaround using Linq to Entities?

Using LINQ in C#, I have the following problem;

I need to select rows from a big table, using 3 conditions: - "schooljaar" needs to be a value, set before, - "p_bamatype" needs to be a value NOT in a list defined in settings (this is a StringCollection) - "p_stdgeb" needs to be a value NOT in a list defined in settings (this is also a StringCollection)

I have this code:

var set = (db.SA_Opleiding.Where(opleiding => opleiding.schooljaar == schooljaar
                                 &&
                                 !Properties.Settings.Default.Admin_Studiegebieden_Exclude.Cast
                                                           <string>().ToList().Contains(
                                                               opleiding.p_stdgeb.ToString())
                                 &&
                                 !Properties.Settings.Default.Admin_Studietypes_Exclude.Cast
                                                           <string>().ToList().Contains(
                                                               opleiding.p_bamatype.ToString()))
                          .Select(opleiding => new OpleidingModel()
                                    {
                                        Id = opleiding.p_opleiding,
                                        LanNames =
                                            new Dictionary
                                            <string, string>()
                                                {
                                                    {
                                                        "NL",
                                                        opleiding.
                                                        opleidingNL
                                                        },
                                                    {
                                                        "FR",
                                                        opleiding.
                                                        opleidingFR
                                                        },
                                                    {
                                                        "EN",
                                                        opleiding.
                                                        opleidingEN
                                                        }
                                                }
                                    }))
                         .ToList<OpleidingModel>();

        return set;

However, LINQ fails converting the Contains method. I read about others having the same issue, but I can't seem to find a decent solution for this. Is there really any solution for the problem described? So what I exactly need is a NOT IN (collection of strings) LINQ equivalent.

Community
  • 1
  • 1
Mortana
  • 1,332
  • 3
  • 15
  • 29
  • [Here's](http://stackoverflow.com/questions/88473/how-to-do-a-where-in-values-in-linq-to-entities-3-5) one of the many possible duplicates. – M.Babcock Jan 22 '12 at 02:31

2 Answers2

2

If one of the various duplicate answers doesn't help, here is a link to one that might. It references an extension to Linq-to-entities:

public static class QueryExtensions
{
    public static IQueryable<TEntity> WhereIn<TEntity, TValue>
    (
        this ObjectQuery<TEntity> query,
        Expression<Func<TEntity, TValue>> selector,
        IEnumerable<TValue> collection
    )
    {
        ParameterExpression p = selector.Parameters.Single();

        //if there are no elements to the WHERE clause,
        //we want no matches:
        if (!collection.Any()) return query.Where(x=>false);

        if (collection.Count() > 3000) //could move this value to config
            throw new ArgumentException("Collection too large - execution will cause stack overflow", "collection");

        IEnumerable<Expression> equals = collection.Select(value =>
           (Expression)Expression.Equal(selector.Body,
                Expression.Constant(value, typeof(TValue))));

        Expression body = equals.Aggregate((accumulate, equal) =>
            Expression.Or(accumulate, equal));

        return query.Where(Expression.Lambda<Func<TEntity, bool>>(body, p));
    }
}

There are several others like it available.

EDIT

I've provided context for the code above, and here is possible usage:

db.SA_Opleiding.WhereIn(v => v.SomeCollection);

I haven't ever used this specific extension method, but they're all basically based on the same principle.

M.Babcock
  • 18,753
  • 6
  • 54
  • 84
  • Thanks for your answer, but where am I supposed to put this code then? – Mortana Jan 22 '12 at 02:37
  • Assuming you're using .NET 3.5 (I believe), in a static class accessible from the code you plan to execute. For more information, please reference [Extension Methods (C# Programming Guide)](http://msdn.microsoft.com/en-us/library/bb383977.aspx). – M.Babcock Jan 22 '12 at 02:40
  • @Mortana - I've updated my answer to include semi-valid context. – M.Babcock Jan 22 '12 at 02:52
  • Thanks, I got this working, however, I need the NotWhereIn equivalent. And I need it twice (so twice NOT IN () AND NOT IN ()). Could you provide me with an example for this? Thanks! – Mortana Jan 22 '12 at 02:58
  • I did the googling for you once. Should I really do it again? – M.Babcock Jan 22 '12 at 03:00
  • I'd appreciate it, I can't seem to find any decent solution, might be looking wrong/using the wrong keys(LINQ NOT WHERE IN) – Mortana Jan 22 '12 at 03:10
  • How about [this answer](http://stackoverflow.com/a/374703/635634) from [this duplicate](http://stackoverflow.com/questions/374267/contains-workaround-using-linq-to-entities) (the same question I've flagged this question as a duplicate of). – M.Babcock Jan 22 '12 at 03:14
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/6933/discussion-between-mortana-and-m-babcock) – Mortana Jan 22 '12 at 03:34
  • @Mortana - No, I'm not going to discuss a widely discussed issue in chat. If you need help implementing it then google can be your console. – M.Babcock Jan 22 '12 at 03:37
0

Substituting the .Any() method for Contains() worked for me. I replaced:

objListing.Contains(myObject)

with

objListing.Any(x => x.Object.ID == myObject.ID)
Judo
  • 5,167
  • 3
  • 24
  • 34