在实体框架查询的选择子句中使用函数

本文关键字:函数 子句 选择 实体 框架 查询 | 更新日期: 2023-09-27 17:59:59

我想针对实体框架实现以下逻辑。

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;
}

由于在select子句中调用了TweakValue(),所以这将不起作用。我知道查询被转换为SQL,问题是TweakValue()无法转换为SQL。我的问题是,实现这一点最经济的方法是什么。我需要第二个循环来转换值吗?

我仍在努力适应LINQ表达式。

在实体框架查询的选择子句中使用函数

最简单的方法可能只是将执行"移动"到客户端以执行转换。在这种情况下,您只需使用:

var items = myContext.Select(item => new { item.Value1, item.Value2 })
                     .AsEnumerable()
                     .Select(item => new {
                                 Value1 = TweakValue(item.Value1),
                                 Value2 = TweakValue(item.Value2)
                             });

请注意,您不需要来重用Value1Value2的名称,这是最容易做到的

如果您真的想使用查询表达式:

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)
            };

您不需要循环,只需要另一个投影:

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实际执行的操作,您可以将整个操作推送到服务器。在你当前的例子上Riffing:

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可以做的事情时,这才有效。