[英]Lambda Contains in SimpleRepository.Find
In SubSonic 3.04's SimpleRepository, I cannot seem to perform a Contains
operation within a lambda expression. 在SubSonic 3.04的SimpleRepository中,我似乎无法在lambda表达式内执行
Contains
操作。 Here's a trivial example: 这是一个简单的例子:
SimpleRepository repo = new SimpleRepository("ConnectionString");
List<int> userIds = new List<int>();
userIds.Add(1);
userIds.Add(3);
List<User> users = repo.Find<User>(x => userIds.Contains(x.Id)).ToList();
I get the error message: 我收到错误消息:
variable 'x' of type 'User' referenced from scope '', but it is not defined
范围“”引用了类型为“用户”的变量“ x”,但未定义
Am I missing something here, or does SubSonic not support Contains
in lambda expressions? 我在这里缺少什么吗,还是SubSonic不支持lambda表达式中的
Contains
? If not, how would this be done? 如果没有,该怎么做?
Since neither of these seem to work... 由于这些似乎都不起作用...
x => guids.Contains(x.Guid)
x => guids.Any(y => y == x.Guid)
... we write a custom lambda expression builder that generates: ...我们编写了一个自定义lambda表达式生成器,该生成器生成:
x => x.Id == {id1} OR x.Id == {id2} OR x.Id == {id3}
This is a trivial scenario, but demonstrates how GetContainsId<User>(ids, repo)
will find all Users with an Id that matches something in the supplied list. 这是一个简单的场景,但演示了
GetContainsId<User>(ids, repo)
如何找到ID与提供的列表中的某些内容匹配的所有Users。
public List<T> GetContainsId<T>(List<int> ids, SimpleRepository repo)
where T : Record, new() // `Record` is a base class with property Id
{
ParameterExpression x = Expression.Parameter(typeof(T), "x");
LambdaExpression expr;
if (ids.Count == 0)
{
expr = Expression.Lambda(LambdaExpression.Constant(false), x);
}
else
{
expr = Expression.Lambda(BuildEqual(x, ids.ToArray()), x);
}
return repo.Find<T>((Expression<Func<T,bool>>)expr).ToList();
}
private BinaryExpression BuildEqual(ParameterExpression x, int id)
{
MemberExpression left = Expression.Property(x, "Id");
ConstantExpression right = Expression.Constant(id);
return Expression.Equal(left, right);
}
private BinaryExpression BuildEqual(ParameterExpression x, int[] ids, int pos = 0)
{
int id = ids[pos];
pos++;
if (pos == ids.Length)
{
return BuildEqual(x, id);
}
return Expression.OrElse(BuildEqual(x, ids, pos), BuildEqual(x, id));
}
Subsonic probably isn't able to convert the userIds.Contains
because it is unable to translate that list into something it can execute on a SQL database. Subsonic可能无法转换
userIds.Contains
因为它无法将该列表转换为可以在SQL数据库上执行的内容。 You'll probably have to resort into explictely defining an or condition: 您可能必须诉诸于明确定义or条件:
repo.Find<User>(x => x.Id == 1 || x.Id == 3).ToList();
I'm pretty sure this will work if you use an IEnumerable instead of a List. 我很确定,如果您使用IEnumerable而不是List,它将可以正常工作。 So the following should work:
因此,以下应该工作:
SimpleRepository repo = new SimpleRepository("ConnectionString");
IEnumerable<int> userIds = new List<int>();
userIds.Add(1);
userIds.Add(3);
List<User> users = repo.Find<User>(x => userIds.Contains(x.Id)).ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.