【问题标题】:Specified method is not supported MySql Entity Framwork 6MySql Entity Framework 6 不支持指定的方法
【发布时间】:2014-06-12 01:40:17
【问题描述】:

我正在尝试从 MySQL 客户端运行以下 Linq 查询

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

这段代码看起来不错,但报错:

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

这在我看来像是 .Intersect 的问题。谁能告诉我这个错误的原因以及如何解决它?

【问题讨论】:

    标签: mysql linq entity-framework c#-4.0 linq-to-mysql


    【解决方案1】:

    我认为@GertArnold 的帖子是正确且最好的答案,但我想知道您为什么得到NotSupportedException 呢?所以问题应该不是来自intersect

    customerRoleIds 来自哪里?是IQueryable<T> 吗?

    打断查询,一步一步完成。

    如果您在这行没有遇到异常:

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

    你必须通过这个得到结果:

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

    如果你通过上面的查询得到异常,你可以尝试这个最终的解决方案来先获取数据,但请注意,所有数据都会先在内存中获取:

    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();
    

    【讨论】:

    • 我认为 Intersect 不受支持,因此 NotSupportedException。但我找不到任何支持的 LINQ 方法的文档。
    • linq 将支持您提供的所有可以转换为expression tree 的函数,所有提供者都默认支持一些称为canonical functions 的函数,您可以在此处阅读有关此函数的信息:@ 987654321@
    • 我认为问题可能也来自intersect,但是您告诉过,当您完成 GertArnold 的解决方案时遇到了同样的错误,而他的解决方案没有 intersect !!!
    • Intersect 是一个集合函数,而不是一个规范的 SQL 函数。每个提供商都可以选择是否以及如何支持它。 Any 也是如此。当提供商没有提供关于这部分的明确文档时,这很可悲。
    • @GertArnold 是的,你说得对,我发布了规范函数文档链接以获取更多信息
    【解决方案2】:

    使用IntersectExcept 对于 LINQ to SQL 后端可能总是很麻烦。使用 Sql Server,它们可能会产生可怕的 SQL 查询。

    通常支持Contains,因为这很容易转换为SQL IN 语句。您的查询可以重写为

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

    我认为customerRoleIds 不会包含很多项目(通常不会有数百个角色),否则请注意不要点击maximum number of items allowed in an IN statement

    【讨论】:

    • 您使用的是哪个版本的 dotConnect?
    • mysql 连接器 6.8.3
    • 连接器不支持Any吗?
    【解决方案3】:

    尝试在相交之前添加 toList(),这应该在本地枚举结果而不是在 MySql 上运行,你会得到性能打击的想法。

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

    【讨论】:

    • 仍然给出相同的错误,同时过滤其他字段,当尝试检查“查询”对象时,它显示了 My Sql 查询,但是当这个(相交)语句运行时,它显示“查询”作为对象。
    • 您的 customerRoleIds 被枚举了对吗?如果不是 toList() 他们也是。
    • @fez 我已经进行了编辑尝试,请告诉我进展如何。
    • 现在给出语法错误:无法将类型'System.Collections.Generic.IEnumerable'隐式转换为'bool'
    • 去掉最后的.Any()
    【解决方案4】:
    query.Where(c => c.CustomerRoles
                     .Any(v=>customerRoleIds.Any(e=>e == v.Id))
         .Select(cr => cr.Id))
         .ToList();
    

    【讨论】:

    • 给出语法错误:bool 不包含 'Select' 的定义并且没有扩展方法
    猜你喜欢
    • 2014-10-04
    • 2013-10-14
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多