假设我有一个表Foo
与表Bar
有一对多关系。
这两个表都有很多列,因此当我使用EntityFramework来获取它们时,我只想选择需要填充适当的DTO的列。
Expression<Func<BAR, BarDto>> BarToDto()
{
return T => new BarDto(){
Id = T.id,
Text = T.text
}
}
using (ModelContainer m = new ModelContainer())
{
var returnVal = m.BAR.Select(BarToDto()).ToList();
}
现在,当我选择表单Foo
时,我还想选择关联的Bar
行,所以我将使用类似的东西:
Expression<Func<FOO, FooDto>> FooToDto()
{
return T => new FooDto(){
Id = T.id,
Text = T.text,
Bars = T.BAR.Select(B => new BarDto(){
Id = B.id,
Text = B.text
}).ToList()
}
}
using (ModelContainer m = new ModelContainer())
{
var returnVal = m.FOO.Select(FooToDto()).ToList();
}
但是我一直在尝试重用BarToDto()
表达式中的代码,最终发现LinqKit
。
通过阅读LinqKit GitHub指令,它说您应该在查询的表上使用.AsExpandable()
,然后可以在另一个表中调用该表达式:
T.BAR.Select(BarToDto().Compile()).ToList()
因为根据LinqKit GitHub页面:
编译实际上从未运行; LINQ to SQL或Entity Framework也从未看到过它。通过调用AsExpandable创建的特殊包装将对Compile的调用完全剥离,并替换为正确的表达式树。
给出的另一种选择是直接在我们要使用的表达式上使用.Expand()
T.BAR.Select(BarToDto().Expand().Compile()).ToList()
而不是使用.AsExpandable()
,但是事实是,这两种方法都导致一个Internal .NET Framework Data Provider error 1025.
,如果我使用.Compile()
(并且将Expression>变成没有LinqKit
的Func <>)。
后来,我在此站点上发现an answer,说我需要在调用.Invoke()
之前将表达式分配给局部变量,如下所示:
Expression<Func<FOO, FooDto>> FooToDto()
{
var BarExpr = BarDto();
return T => new FooDto()
{
Id = T.id,
Text = T.text,
Bars = T.BAR.Select(b => BarExpr.Invoke(b)).ToList()
}
}
但这反过来会导致LINQ to Entities does not recognize the method 'BarDto Invoke[BAR,BarDto](System.Linq.Expressions.Expression´1[System.Func´2[BAR,BarDto]], BAR)' method, and this method cannot be translated into a store expression.
是否有必要在ModelContainer中进行某些配置以使用LinqKit
扩展方法,还是类似这样的应用程序超出了LinqKit的功能?