在 select 子句中应用函数

Applying a function within the select clause

我有一个查询(长连接等),对于 select 子句中的某些字段(所有这些都是 decimal? 类型),我想 return null 当数据库将它们存储为 0 时。正确完成以下工作:

var q =
    from O in ....
    ....
    select new
    {
        ...
        Spot = O.Spot == 0 ? null : O.Spot,
        Moneyness = O.Strike / (O.Spot == 0 ? null : O.Spot),
        Volatility = O.Rate == 0 ? null : O.Rate
    };

但我更愿意将 0 的检查封装在一个函数中。所以我尝试了

private static decimal? NullIfZero(decimal? obj)
{
    return  obj == 0 ? null : obj;
}

然后

var q =
    from O in ....
    ....
    select new
    {
        ...
        Spot = NullIfZero(O.Spot),
        Moneyness = O.Strike / NullIfZero(O.Spot),
        Volatility = NullIfZero(O.Rate)
    };

但现在我得到错误:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Data.Linq.dll

Additional information: Could not translate expression 'NullIfZero(<>h__TransparentIdentifier0.O.Spot)' into SQL and could not treat it as a local expression.

如果我只是尝试,我不会收到错误

var q =
    from O in ....
    ....
    select new
    {
        ...
        Spot = NullIfZero(O.Spot),
        Moneyness = O.Strike / (O.Spot == 0 ? null : O.Spot),
        Volatility = NullIfZero(O.Rate)
    };

但我看不出 NullIfZero(O.Spot)(O.Spot == 0 ? null : O.Spot) 之间有什么区别,尤其是当它似乎只在用作除数时才有效。

第一个查询失败,因为 L2S 无法翻译函数调用 NullIfZero。第二个查询有效,因为 L2S 可以评估局部函数,如果它们是查询中最后 Select 的一部分。这是 EF 目前缺少的一个非常好的功能。

解决方案:

  1. 内联函数。
  2. 从谓词生成器库中尝试 AsExpandable