1

I am trying to run the following Linq query from MySQL client

    query = query.Where(c => c.CustomerRoles
                              .Select(cr => cr.Id)
                              .Intersect(customerRoleIds)
                              .Any()
                       );

This code looks okay, but gives the error:

System.NotSupportedException: Specified method is not supported.at MySql.Data.Entity.SqlGenerator.Visit(DbIntersectExpression expression)

This looks to me like an issue with .Intersect. Can anybody tell me the cause of this error and how to fix it?

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291

4 Answers4

3

i think @GertArnold's post is a correct and best of the answers, but i'm wonder why have you gotten NotSupportedException yet ? so the problem should not be from intersect probably.

where is customerRoleIds come from ? is it IQueryable<T> ?

break the query, and complete it step by step.

if you don't get exception at this lines:

var a = query.Select(c => new { 
        c, 
        CustomerRoleIDList = c.CustomerRoles.Select(cr => cr.Id).AsEnumerable()
    })
    .ToList();

var b = customerRoleIds.ToList();

you must get the result by this:

var b = query.Where(c => c.CustomerRoles.any(u => customerRoleIds.Contains(u.Id)))
    .ToList();

if you get exception by above query, you can try this final solution to fetch data first, but note by this, all data will be fetched in memory first:

var a = query.Select(c => new { 
        c, 
        CustomerRoleIDList = c.CustomerRoles.Select(cr => cr.Id).AsEnumerable() 
    })
    .ToList();

var b = a.Where(c => c.CustomerRoleIDList.any(u => customerRoleIds.Contains(u)))
    .Select(u => u.c)
    .ToList();
Amir Sherafatian
  • 2,083
  • 2
  • 20
  • 32
  • I think `Intersect` is not supported, hence the `NotSupportedException`. But I can't find any documentation of supported LINQ methods. – Gert Arnold May 06 '14 at 07:05
  • all function which your provide can translate to `expression tree` will be supported in linq, some functions which is called `canonical functions` is supported by default by all providers, you can read about this functions here: http://msdn.microsoft.com/en-us/library/vstudio/bb738626(v=vs.100).aspx – Amir Sherafatian May 06 '14 at 07:41
  • i think probably the problem is from `intersect` too, but you told, got same error when you done GertArnold's solution, and his solution was without `intersect` !!! – Amir Sherafatian May 06 '14 at 07:44
  • `Intersect` is a set function, not a canonical SQL function. Each provider can choose whether and how to support it. The same goes for `Any`. It's sad when a provider doesn't offer clear documentation on this part. – Gert Arnold May 06 '14 at 07:47
  • @GertArnold yes, you right, i posted canonical function documentation link for more information – Amir Sherafatian May 06 '14 at 09:09
2

Using Intersect or Except is probably always troublesome with LINQ to a SQL backend. With Sql Server they may produce horrible SQL queries.

Usually there is support for Contains because that easily translates to a SQL IN statement. Your query can be rewritten as

query = query.Where(c => c.CustomerRoles
                 .Any(cr => customerRoleIds.Contains(cr.Id)));

I don't think that customerRoleIds will contain many items (typically there won't be hundreds of roles), otherwise you should take care not to hit the maximum number of items allowed in an IN statement.

Community
  • 1
  • 1
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
1

Try adding toList() before intersect, that should enumerate results locally instead running on MySql, you will get performance hit thought.

 query = query.Where(c => c.CustomerRoles.Select(cr => cr.Id)).ToList().Intersect(customerRoleIds);
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
1
query.Where(c => c.CustomerRoles
                 .Any(v=>customerRoleIds.Any(e=>e == v.Id))
     .Select(cr => cr.Id))
     .ToList();
Honorable Chow
  • 3,097
  • 3
  • 22
  • 22