如何使用EF查询中的函数参数化选择器?
我有一个投影函数,我传递给IQueryable.Select()
方法:
private static Expression<Func> GetPriceSelector(){ return e => new PriceItem { Id = e.Id, Price = Math.Round(e.Price, 4) }; }
一切正常,但我想像这样参数化:
private static Expression<Func> GetPriceSelector(Func formula){ return e => new PriceItem { Id = e.Id, Price = formula(e) }; }
所以我可以称之为
prices.Select(GetPriceSelector(e => Math.Round(e.Price, 4)))
不幸的是,EF抱怨它:
LINQ to Entities中不支持LINQ表达式节点类型“Invoke”
如何重写代码让EF快乐?
首先, GetPriceSelector
方法需要接受表达式而不是函数。 不同之处在于表达式是代码作为数据,因此可以将其转换为SQL,而函数是编译代码,因此无法将其转换为SQL。
接下来,您需要一种方法来合并这两个表达式。 手动执行此操作很难。 幸运的是,有一个名为LINQKit的库可以做到这一点。 以下是使用LINQKit解决问题的方法:
private static Expression> GetPriceSelector( Expression> formula) { Expression> expression = e => new PriceItem { Id = e.Id, Price = formula.Invoke(e) //use the forumla expression here }; return expression.Expand(); //This causes formula.Invoke(e) to be converted //to something like Math.Round(e.Price, 4) }