【问题标题】:Entity Framework Core LINQ Tree Expression Problem with ConcatConcat 的实体框架核心 LINQ 树表达式问题
【发布时间】:2020-03-11 17:51:58
【问题描述】:

所以我有一个 IQueryable 扩展,它的功能比这段代码多一点。本质上,我正在组合一堆字符串,然后对它们进行包含。我遇到的问题是 Entity Framework Core 不支持 System.String.Concat,并在本地执行这部分查询,这绝对不是我想要的。

这是我用来将这些不同字符串添加在一起的小循环:

                List<Expression> stringExpressionsToConcat = new List<Expression>();
                foreach (var member in memberExpressions)
                {
                    stringExpressionsToConcat.Add(member);
                    stringExpressionsToConcat.Add(spaceConstant);
                }
                //call the concat to create the final term to search on
                NewArrayExpression arrayExpression = Expression.NewArrayInit(typeof(string), stringExpressionsToConcat);
                searchStringExpression = Expression.Call(concatMethod, arrayExpression);

这是工作客户端,但不会为 Entity to SQL 编译。我在 Order By 子句中遇到了同样的问题,我正在做这样的事情:

.ThenByDescending(e => string.Concat(e.FirstName, " ", e.LastName))

这显然也没有将实体转换为 SQL,因为它正是我在表达式树中构建的。但是,将其更改为这个....

.ThenByDescending(e => e.FirstName + " " + e.LastName)

确实将实体转换为 SQL。所以我想知道如何创建上面代码中表示的正确发送到 SQL 的相同表达式。我试过使用 Expression.Add 但表达式生成器中的字符串类型不支持添加。这是可能的,还是实体框架中有一些额外的代码使这成为可能?我尝试在 GitHub 上探索源代码,但要找到它发生的确切位置有点让人不知所措。

【问题讨论】:

    标签: c# .net-core entity-framework-core expression-trees


    【解决方案1】:

    啊哈!我已经想通了!!此表达式树表现出相同的行为并将数据发送到 SQL!

    修改后的代码如下:

    //more than one member has the property, we need to combine them with spaces in between
    List<Expression> stringExpressionsToConcat = new List<Expression>();
    foreach (var member in memberExpressions)
    {
        stringExpressionsToConcat.Add(member);
        stringExpressionsToConcat.Add(spaceConstant);
    }
    
    searchStringExpression = stringExpressionsToConcat[0];
    for (int i = 1; i < stringExpressionsToConcat.Count; i++)
    {
        searchStringExpression = Expression.Add(searchStringExpression, 
        stringExpressionsToConcat[i], typeof(string).GetMethod("Concat", new[] { 
        typeof(string), typeof(string) }));
    }
    

    这种变化从实体框架在 2.2 中引发警告(以及 3.1 中的错误)到将其转换为以下 SQL 代码!

    ([e].[MemberExpression1] + N' ') + [e].[MemberExpression2]) + N' ') + [e].[MemberExpression3]) + N' ')
    

    这正是 Entity Framework 生成 SQL 子句的方式,我在我的回答中谈到了 Order By!我不确定原因是什么……但是,如果您希望创建自己的表达式树,将 Entity Framework Core 树访问者可以转换为 sql 的字符串相加,就是这样!

    感谢这个答案为我指明了正确的方向: https://stackoverflow.com/a/3858421/5245385

    【讨论】:

      【解决方案2】:

      基本上:等待 EfCore 在某个时候支持此功能,或者现在使用 Ef classic。

      EfCore 对 LINQ 的支持非常有限 - 感觉有点像开发它的人从未使用过它,也从未阅读过 LINQ 所能提供的所有内容。没有解决方法。

      在 EfCore 2.2 中,它正在执行客户端评估 - 在 3.1 中,它被禁用,它告诉您去进行不同的编程。

      如果您愿意,请在 github 页面上打开一个问题,然后也许有人会为 11 月的 5.0 版本选择它。机会是没有的,因为这有点神秘,而且他们遇到了更常见的问题。

      【讨论】:

      • 所以要明确一点,除了 Concat 之外,绝对没有办法在表达式树中表示 stringType + stringType?我知道不支持 Concat,但幕后发生的事情是允许 stringType + stringType 正确转换为 SQL,我只是不知道如何编写该表达式树。
      • 你不这样做,因为这不是关于你编写它 - 它是关于你编写它并且 EfCore 树访问者不会抛出异常,因为它找到了一组不受支持的节点。就这么简单。
      • 我想通了并发布了答案。对于我的问题,我不确定我们是否在同一页面上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 2016-11-27
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      相关资源
      最近更新 更多