简体   繁体   English

编译之前如何将变量传递给Expression Func Projection

[英]How to pass variables to Expression Func Projection before compile

I am trying to write Expression Functions for my projections. 我正在尝试为我的投影编写表达函数。 I found a good article about that link . 我找到了一篇有关该链接的好文章。 But I couldn't figure out how can I pass variables to these functions. 但是我不知道如何将变量传递给这些函数。

How can I write a projection function for this one 我如何为此编写一个投影函数

int i = 3;
var query = await _db.Users
                .FilterByName(name)
                .Select(item => new SearchResultItemViewModel
                {
                    Id = item.Id,
                    Article = item.FirstName + i.ToString()
                });
}))

This one is working. 这个正在工作。 In select SQL string has only Id and Firstname but I can't pass any variable. 在选择SQL字符串中只有Id和Firstname,但是我不能传递任何变量。

   var query = await _db.Users
                .FilterByName(name)
                .Select(item => SearchResultItemViewModel.Projection)
public static Expression<Func<ApplicationUser, SearchResultItemViewModel>> Projection
        {
            get
            {
                return item => new SearchResultItemViewModel
                {
                    Id = item.Id,
                    Article = item.FirstName
                };
            }
        }

This one is working only if you call compile and invoke. 仅当您调用编译和调用时,此命令才有效。 SQL string has all rows. SQL字符串包含所有行。 Leading to bad performance 导致性能不佳

   var query = await _db.Users
                .FilterByName(name)
                .Select(item => SearchResultItemViewModel.Projection.Compile().Invoke(item,i))
public static Expression<Func<ApplicationUser,int, SearchResultItemViewModel>> Projection
        {
            get
            {
                return( item,i) => new SearchResultItemViewModel
                {
                    Id = item.Id,
                    Article = item.FirstName + i.ToString()
                };
            }
        }

I don't use EF so this might vary in your specific use case, but this seems to be a question about LINQ Expressions more than anything else. 我不使用EF,因此在您的特定用例中可能会有所不同,但这似乎是有关LINQ表达式的一个问题,而不是其他任何问题。

The first big problem is that you are trying to use an Expression<Func<ApplicationUser, int, SearchResultItemViewModel>> where you really meant Expression<Func<ApplicationUser, SearchResultItemViewModel>> and that's not going to do what you want. 第一个大问题是,您尝试使用Expression<Func<ApplicationUser, int, SearchResultItemViewModel>> ,实际上您的意思是Expression<Func<ApplicationUser, SearchResultItemViewModel>>而这并没有做您想要的事情。 Instead of binding to a variable you're invoking the indexed variant of Select . 而不是绑定到变量,而是调用Select索引变体 So instead of getting the same value of i for all rows you get the index of the row. 因此,您不必为所有行都获得相同的i值,而是获得行的索引。

When you create an expression that references a variable, one of two things happens. 创建引用变量的表达式时,会发生以下两种情况之一。 For local variables (and parameters) the value is copied to an anonymous class instance which is bound to the expression, so you can't change it afterwards. 对于局部变量(和参数),该值将复制到绑定到该表达式的匿名类实例,因此您之后将无法对其进行更改。 For other variables the expression contains a reference to the variable itself, as well as the containing object for non-static variables. 对于其他变量,表达式包含对变量本身的引用,以及非静态变量的包含对象。

Which means that you could in principle use a static variable to alter the parameter and never have to recreate the projection expression. 这意味着您原则上可以使用静态变量来更改参数,而不必重新创建投影表达式。 There are certainly times when this is useful. 当然有时候这很有用。

On the other hand, your code above is creating a new instance each time you access the Projection property. 另一方面,每次访问Projection属性时,上面的代码都会创建一个新实例。 So why not just change it to a function and generate the expression you need when you need it? 那么,为什么不将其更改为函数并在需要时生成所需的表达式呢?

public static Expression<Func<ApplicationUser, SearchResultItemViewModel>> Projection(int parm)
    => item => new SearchResultItemViewModel
        {
            Id = item.Id,
            Article = item.FirstName + parm.ToString()
        };

Each time you invoke the method you'll get back an expression that uses the specified value. 每次调用该方法时,都将返回一个使用指定值的表达式。

Or you could use an expression visitor to take a template expression and modify the constants in it to whatever you need at the time. 或者,您也可以使用表达式访问者来获取模板表达式并将其常量修改为您当时需要的任何值。 Fun, but a bit beyond scope here I think. 好玩,但我认为这里有点超出范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM