带有Concat的实体框架核心LINQ树表达问题

时间:2020-03-11 17:51:58

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

因此,我有一个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编译为SQL。我在执行以下操作的Order By子句中遇到了相同的问题:

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

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

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

是否将Entity转换为SQL。所以我想知道如何创建上面代码中表示的相同表达式,并将其正确发送到SQL。我尝试使用Expression.Add,但表达式构建器中的字符串类型不支持add。这可能吗?或者实体框架中是否有一些额外的代码可以实现?我曾尝试在GitHub上探索源代码,但要确切地找到它的发生位置却有点不知所措。

2 个答案:

答案 0 :(得分:3)

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

下面的修改代码:

Shader "Custom/HoleMaker" {
    Properties{
            _Position("Position", Vector) = (0,0,0,0)
            _Scale("Scale", Vector) = (1,1,1,0)
            _Radius("Radius", Range(0,1)) = 0.01
            _Color("Color", Color) = (1,1,1,1)
            _CutawayColor("Cutaway Color", Color) = (1,1,1,1)
    }
            SubShader{
                    Tags { "RenderType" = "Opaque"}
                    LOD 200
                    Cull Front

                    CGPROGRAMtypes
                    #pragma surface surf MonoColor fullforwardshadows vertex:vert

                    // Use shader model 3.0 target, to get nicer looking lighting
                    #pragma target 3.0

                    fixed4 _CutawayColor;

                    float4 _Position;
                    float4 _Scale;
                    float _Radius;

                    struct Input
                    {
                            float2 uv_MainTex;
                            float3 worldPos;
                    };

                    void vert(inout appdata_full v, out Input o)
                    {
                            UNITY_INITIALIZE_OUTPUT(Input, o);
                            v.normal *= -1;
                    }

                    half4 LightingMonoColor(SurfaceOutput s, half3 lightDir, half atten) {
                            return _CutawayColor;
                    }

                    void surf(Input IN, inout SurfaceOutput o)
                    {

                            //spherical clipping
                            float dist = length(_Scale.xyz * IN.worldPos.xyz - _Position.xyz);
                            if (dist < _Radius)
                                    clip(-1);


                            o.Albedo = _CutawayColor.rgb;
                    }
                    ENDCG
            }
                    FallBack "Diffuse"
   }

从Entity Framework发出2.2中的警告(以及3.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) }));
}

这正是Entity Framework生成SQL子句的方式,我在我的回答中使用Order By!我不确定原因是什么...但是,如果您要创建自己的表达式树,这些表达式树将字符串添加在一起,那么Entity Framework Core树访问者可以将其转换为sql!

请使用以下答案来指出正确的方向: https://stackoverflow.com/a/3858421/5245385

答案 1 :(得分:-2)

基本上:请等待EfCore支持该功能,或暂时使用Ef classic。

EfCore在LINQ上提供的支持非常有限-感觉就像开发人员从未使用过它,也从未阅读过LINQ的所有内容。这不是解决方法。

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

如果您愿意,可以在github页面上打开一个问题,然后也许有人会在11月5.0版中选择它。不会的原因是,这有点不可思议,而且它们充满了更常见的问题。