我正在尝试为我的投影编写表达函数。我找到了一篇有关link的好文章。但是我不知道如何将变量传递给这些函数。
我如何为此编写投影功能
int i = 3;
var query = await _db.Users
.FilterByName(name)
.Select(item => new SearchResultItemViewModel
{
Id = item.Id,
Article = item.FirstName + i.ToString()
});
}))
这个正在工作。在select 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
};
}
}
仅当您调用编译并调用时,此命令才起作用。 SQL字符串包含所有行。导致性能不佳
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()
};
}
}
答案 0 :(得分:2)
我不使用EF,所以这可能因您的特定使用情况而异,但这似乎是有关LINQ表达式的一个问题,比其他任何问题都重要。
第一个大问题是,您试图使用Expression<Func<ApplicationUser, int, SearchResultItemViewModel>>
的地方,但实际上并没有达到您想要的目的。而不是绑定到变量,而是调用indexed variant of Select
。因此,您不必为所有行都获得相同的Expression<Func<ApplicationUser, SearchResultItemViewModel>>
值,而是获得行的索引。
创建引用变量的表达式时,会发生以下两种情况之一。对于局部变量(和参数),该值将复制到绑定到该表达式的匿名类实例,因此您之后将无法对其进行更改。对于其他变量,表达式包含对变量本身的引用以及非静态变量的包含对象。
这意味着您原则上可以使用静态变量来更改参数,而不必重新创建投影表达式。当然有时候这很有用。
另一方面,每次访问i
属性时,上面的代码都会创建一个新实例。那么,为什么不只将其更改为函数并在需要时生成所需的表达式呢?
Projection
每次调用该方法时,都会返回一个使用指定值的表达式。
或者您可以使用表达式访问者来获取模板表达式并将其常量修改为您当时需要的任何形式。很有趣,但我认为这里有点超出范围。