我有2个可重用的函数返回列表。如果将这些函数的代码直接写入linq到实体查询,那么一切都很好。但是,将它们分离为函数会导致错误,因为它无法转换为存储的表达式。我确信必须有办法做到这一点。任何想法如何解决这个问题。理想情况下,我希望可重用的部分也可以在linq之外用于实体查询。
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(...)的土地可以看作是一个直接的c#lambda表达式,可以用作Func
它也可以看作是一个表达式>
后者是形成表达式的对象树,换句话说是关于方式的描述,因为传入的参数可以在没有实际可执行代码的情况下被评估为bool,而只是关于该做什么的描述。从参数中取成员a,将其与常量1进行比较...取结果的布尔值:从参数中取出成员b,将其与常量“foo”进行比较...返回布尔AND的结果
为什么这一切?
这是LINQ的工作方式...... LINQ to实体接受表达式树,查看所有操作,找到相应的SQL,并构建一个最终执行的SQL语句......
当你有你提取的Func <...>时,有一点问题...在结果表达式树的某个点上有类似的东西......拿参数x和CALL静态Func ...表达式树做不再包含对Func内部发生的事情的描述,只是对它的调用...只要你想将它编译成.net运行时可执行函数,它就是有趣和游戏......但当你试图将它解析为SQL,LINQ to entiteis不知道相应的SQL为“调用一些c#函数”...因此它告诉你表达式树的这一部分不能转换成存储表达式