Linq To 实体中的可重用函数
Reusable Functions in Linq To Entites
我有 2 个 return 列出的可重用函数。如果将这些函数的代码直接写入 linq to entities 查询,一切都很好。但是,将它们分离到函数中会导致错误,因为它无法转换为存储的表达式。我相信一定有办法做到这一点。任何想法如何解决这个问题。理想情况下,我希望可重用部分也能在 linq to entity 查询之外使用。
var activityBands = DbContext.ActivityBand
.OrderBy(x => x.ActivityBandDescription)
.Where(x => x.Active && x.ClientAccountId == clientAccountId)
.Select(x => new ActivityBandDdl
{
Name = x.ActivityBandDescription,
ActivityBandId = x.ActivityBandId,
ApplyAwr = x.ApplyAwr,
AssignmentLineTimeTypeIds = TimeTypesForActivityBand(x.DailyRate) ,
AssignmentTypeIds = AssTypesForActivityBand(x.StagePayment)
}).ToList();
public static Func<bool, List<int>> TimeTypesForActivityBand =
(dailyRate) => (new int[] { 1, 2, 3, 4 }).Where(t =>
((t != 1 && t != 2) || !dailyRate) //No Timed or NTS for daily rates
).ToList();
public static Func<bool, List<int>> AssTypesForActivityBand =
(stagePayment) => (new int[] { 2,3,4,5,6,7,8,9,10 }).Where(t =>
( t!=2 || !stagePayment) //Only stage pay ass have stage pay activity bands
).ToList();
TL;DR;
针对您的问题的建议解决方案:
获取 LinqKit ... 看看它的 Expand() 函数(在文档中:组合表达式)
https://github.com/scottksmith95/LINQKit#combining-expressions
详情:
问题归结为:两种情况下的查询有什么区别...
LINQ 查询使用表达式树...换句话说:只是因为您直接在查询中键入的代码和您在静态 Func<...> 中键入的代码看起来相同,实际上, 是一样的,两种情况下得到的表达式树是不一样的
什么是表达式树?
想象一个更简单的查询,例如... someIQueryable.Where(x => x.a==1 && x.b=="foo")
传递给 Where(...) 的 lamda 可以看作是一个直接向前的 c# lambda 表达式,可以用作 Func
也可以看做一个表达式>
后者是形成表达式的对象树,换句话说是关于方式的描述,因为传入的参数可以评估为 bool 而无需实际具有可执行代码,而只是关于的描述要做什么...从参数中取出成员 a,equality-compare 将其赋给常量 1 ...将结果与结果进行布尔值与运算:从参数中取出成员 b,equality-compare 它到常量 "foo" ... return 布尔值 AND
的结果
为什么会这样?
这是 LINQ 的工作方式 ... LINQ to entiteis 获取表达式树,查看所有操作,找到相应的 SQL,并构建一个 SQL 语句,该语句在结束...
当你有提取的 Func<...> 时有一个小问题......在生成的表达式树中的某个点有类似......采用参数 x 并调用静态 Func .. . 表达式树不再包含对 Func 内部发生的事情的描述,而只是对其的调用......只要你想将其编译为 .net 运行时可执行函数,这一切都很有趣和游戏......但是当您尝试将其解析为 SQL 时,LINQ to entiteis 不知道 "call some c# function" 对应的 SQL ...因此它告诉您表达式树的这一部分不能转换为存储表达式
我有 2 个 return 列出的可重用函数。如果将这些函数的代码直接写入 linq to entities 查询,一切都很好。但是,将它们分离到函数中会导致错误,因为它无法转换为存储的表达式。我相信一定有办法做到这一点。任何想法如何解决这个问题。理想情况下,我希望可重用部分也能在 linq to entity 查询之外使用。
var activityBands = DbContext.ActivityBand
.OrderBy(x => x.ActivityBandDescription)
.Where(x => x.Active && x.ClientAccountId == clientAccountId)
.Select(x => new ActivityBandDdl
{
Name = x.ActivityBandDescription,
ActivityBandId = x.ActivityBandId,
ApplyAwr = x.ApplyAwr,
AssignmentLineTimeTypeIds = TimeTypesForActivityBand(x.DailyRate) ,
AssignmentTypeIds = AssTypesForActivityBand(x.StagePayment)
}).ToList();
public static Func<bool, List<int>> TimeTypesForActivityBand =
(dailyRate) => (new int[] { 1, 2, 3, 4 }).Where(t =>
((t != 1 && t != 2) || !dailyRate) //No Timed or NTS for daily rates
).ToList();
public static Func<bool, List<int>> AssTypesForActivityBand =
(stagePayment) => (new int[] { 2,3,4,5,6,7,8,9,10 }).Where(t =>
( t!=2 || !stagePayment) //Only stage pay ass have stage pay activity bands
).ToList();
TL;DR; 针对您的问题的建议解决方案:
获取 LinqKit ... 看看它的 Expand() 函数(在文档中:组合表达式) https://github.com/scottksmith95/LINQKit#combining-expressions
详情:
问题归结为:两种情况下的查询有什么区别...
LINQ 查询使用表达式树...换句话说:只是因为您直接在查询中键入的代码和您在静态 Func<...> 中键入的代码看起来相同,实际上, 是一样的,两种情况下得到的表达式树是不一样的
什么是表达式树?
想象一个更简单的查询,例如... someIQueryable.Where(x => x.a==1 && x.b=="foo")
传递给 Where(...) 的 lamda 可以看作是一个直接向前的 c# lambda 表达式,可以用作 Func
也可以看做一个表达式>
后者是形成表达式的对象树,换句话说是关于方式的描述,因为传入的参数可以评估为 bool 而无需实际具有可执行代码,而只是关于的描述要做什么...从参数中取出成员 a,equality-compare 将其赋给常量 1 ...将结果与结果进行布尔值与运算:从参数中取出成员 b,equality-compare 它到常量 "foo" ... return 布尔值 AND
的结果为什么会这样?
这是 LINQ 的工作方式 ... LINQ to entiteis 获取表达式树,查看所有操作,找到相应的 SQL,并构建一个 SQL 语句,该语句在结束...
当你有提取的 Func<...> 时有一个小问题......在生成的表达式树中的某个点有类似......采用参数 x 并调用静态 Func .. . 表达式树不再包含对 Func 内部发生的事情的描述,而只是对其的调用......只要你想将其编译为 .net 运行时可执行函数,这一切都很有趣和游戏......但是当您尝试将其解析为 SQL 时,LINQ to entiteis 不知道 "call some c# function" 对应的 SQL ...因此它告诉您表达式树的这一部分不能转换为存储表达式