我想针对实体框架实现以下逻辑。
var items = from item in myContext
select new {
Value1 = TweakValue(item.Value1),
Value2 = TweakValue(item.Value2)
};
protected int TweakValue(int value)
{
// Custom processing here
return value;
}
由于TweakValue()
子句中对select
的调用,这不起作用。我知道查询转换为SQL,问题是TweakValue()
无法转换为SQL。我的问题是实现这一目标的最经济的方法是什么。我需要第二个循环来转换值吗?
我仍然试图熟悉LINQ表达式。
答案 0 :(得分:11)
最简单的方法可能是将执行“移动”到客户端以执行转换。在这种情况下,您只需使用:
var items = myContext.Select(item => new { item.Value1, item.Value2 })
.AsEnumerable()
.Select(item => new {
Value1 = TweakValue(item.Value1),
Value2 = TweakValue(item.Value2)
});
请注意,您 不能重复使用Value1
和Value2
的名称 - 这是最容易实现的。
如果你真的想使用查询表达式:
var query = from item in myContext
select new { item.Value1, item.Value2 };
var items = from item in query.AsEnumerable()
select new {
Value1 = TweakValue(item.Value1),
Value2 = TweakValue(item.Value2)
};
如果您想先执行过滤,您可以通过在调用AsEnumerable()
之前进行过滤,排序等,在数据库中获得 。例如:
var query = from item in myContext
where item.Foo == bar
orderby item.Something
select new { item.Value1, item.Value2 };
var items = from item in query.AsEnumerable()
select new {
Value1 = TweakValue(item.Value1),
Value2 = TweakValue(item.Value2)
};
答案 1 :(得分:5)
您不需要循环,只需要另一个投影:
var items = myContext.Select(i => new {
Value1 = item.Value1,
Value2 = item.Value2
})
.AsEnumerable()
.Select(i => new {
Value1 = TweakValue(item.Value1),
Value2 = TweakValue(item.Value2)
});
编辑:根据TweakValue
实际执行的操作,您可以将整个操作推送到服务器。重复你当前的例子:
public Expression<Func<Item, ItemProjection>> TweakValue()
{
return item => new ItemProjection
{
Value1 = item.Value1,
Value2 = item.Value2 + 0 // or something else L2E can understand...
};
}
现在使用它:
var exp = TweakValue();
var items = myContext.Select(exp);
注意我将exp
存储在变量中,以便L2E不会尝试在查询中直接调用TweakValue
,这会失败。
当然,这仅在TweakValue
执行L2E可以执行的操作时才有效。