Linq to OData 中关键字段的运算符 "IN"
Operator "IN" by key field in Linq to OData
大家下午好!
我正在尝试翻译 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 的输入列表和 returns 正确的 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();
但在运行时出现错误:
An exception of type 'System.NotSupportedException' occurred in
Microsoft.Data.Services.Client.dll but was not handled in user code
Additional information: The expression (((((False Or (Convert(Int32
Id.GetValue(code)) == 1044)) Or (Convert(Int32 Id.GetValue(code)) ==
8102)) Or (Convert(Int32 Id.GetValue(code)) == 5997)) Or
(Convert(Int32 Id.GetValue(code)) == 7761)) Or (Convert(Int32
Id.GetValue(code)) == 15455)) is not supported.
你知道解决这个问题的方法吗?
你写的泛型方法很不清楚(签名和实现)。据我了解,这个想法是建立这样的表达
x => x.Id == Id1 || x.Id == Id2 || ....
这是使用 Expression.Equal and 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();
大家下午好! 我正在尝试翻译 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 的输入列表和 returns 正确的 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();
但在运行时出现错误:
An exception of type 'System.NotSupportedException' occurred in Microsoft.Data.Services.Client.dll but was not handled in user code
Additional information: The expression (((((False Or (Convert(Int32 Id.GetValue(code)) == 1044)) Or (Convert(Int32 Id.GetValue(code)) == 8102)) Or (Convert(Int32 Id.GetValue(code)) == 5997)) Or (Convert(Int32 Id.GetValue(code)) == 7761)) Or (Convert(Int32 Id.GetValue(code)) == 15455)) is not supported.
你知道解决这个问题的方法吗?
你写的泛型方法很不清楚(签名和实现)。据我了解,这个想法是建立这样的表达
x => x.Id == Id1 || x.Id == Id2 || ....
这是使用 Expression.Equal and 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();