操作员”;IN”;按Linq到OData中的键字段

本文关键字:字段 OData Linq IN 操作员 | 更新日期: 2023-09-27 18:28:26

大家下午好!我正在尝试翻译SQL中的请求:

SELECT *
FROM TABLE1
WHERE TABLE1.ID IN (SELECT ID FROM TABLE2)

转换为LINQ to OData。只要ODAta协议不支持"IN",WHERE部分就必须像TABLE1.ID=1 OR TABLE1.ID=2 OR ...一样,我已经尝试过对泛型方法进行编码,该方法将id的列表作为输入,并以这种方式返回LINQ的正确表达式:

public static Expression<Func<T,bool>> Lambda<T>(this Expression expr ,List<int> ids)
    {
        ParameterExpression argParam = Expression.Parameter(typeof(T), "rep");
        Expression<Func<T, bool>> lambda = code => 1 == 0;
        var lambdaPred = Expression.Lambda<Func<T, bool>>(lambda.Body, argParam);
        var attr = (DataServiceKeyAttribute)typeof(T).GetCustomAttribute(typeof(DataServiceKeyAttribute));
        string keyName;
        try
        {
            keyName = attr.KeyNames.FirstOrDefault();//get name of key attribute
        }
        catch
        {
            return null;
        }
        foreach (int id in ids)
        {
            var property = typeof(T).GetProperty(keyName);
            Expression<Func<T, bool>> lambdatemp = code => (int)property.GetValue(code) == id;                               
            var tmp = Expression<Func<T, bool>>.Or(lambdaPred.Body, lambdatemp.Body);                
            lambdaPred = Expression.Lambda<Func<T, bool>>(tmp, argParam);
        }
        return lambdaPred;
    }

这种方法的用法:

Expression<Func<Client, bool>> lambda = code => 1 == 0;
var query = lambda.Body.Lambda<Client>(ids);
var retr = clientRepository.Retrieve(query).ToList();

但在运行时,我会出现错误:

中发生类型为"System.NotSupportedException"的异常Microsoft.Data.Services.Client.dll,但未在用户代码中处理

附加信息:表达式Id.GetValue(代码))==1044)或(转换(Int32 Id.GetValue(代码)==8102))或(转换(Int32 Id.GetValue(code))==5997)或(转换(Int32 Id.GetValue(code))==7761)或(转换(Int32Id.GetValue(代码))==15455))。

你知道解决这个问题的方法吗?

操作员”;IN”;按Linq到OData中的键字段

您编写的泛型方法非常不清楚(签名和实现)。据我所知,这个想法是建立像这样的表达

x => x.Id == Id1 || x.Id == Id2 || ....

以下是使用Expression.Equal和Expression.OrElse 实现这种方法的一种可能方法

public static class PredicateHelper
{
    public static Expression<Func<T, bool>> In<T>(this Expression<Func<T, int>> idSelector, IEnumerable<int> ids)
    {
        Expression body = null;
        foreach (var id in ids)
        {
            var operand = Expression.Equal(idSelector.Body, Expression.Constant(id));
            body = body == null ? operand : Expression.OrElse(body, operand);
        }
        return body != null ? Expression.Lambda<Func<T, bool>>(body, idSelector.Parameters) : null;
    }
}

示例用法相当于您的示例

var idFilter = PredicateHelper.In((Client c) => c.Id, ids);
var result = clientRepository.Retrieve(idFilter).ToList();