在LINQ to Entities中没有办法再像 LINQ to SQL 中一样使用 Contains 的方法来实现sql "in" 关键字
下面代码在 LINQ to SQL 中可行 在LINQ to Entities却无法运行:
var s
=
db.Account.Select(c
=>
c.ID);
var ret = (from t in db.Profile
where s.Contains(t.ID)
select t).ToList();
var ret = (from t in db.Profile
where s.Contains(t.ID)
select t).ToList();
替代方法1:使用方法Any
var ids
=
db.Account.Select(c
=>
c.ID);
var ret = (from t in db.Profile where ids.Any(c => c == t.UserID) select t).ToList();
var ret = (from t in db.Profile where ids.Any(c => c == t.UserID) select t).ToList();
使用方法Any替换法搞了好久都没法实现直接对数组Any,下列代码仍无法执行:
int
[] ids
=
new
int
[]{
10101
,
10005
,
10007
};
var ret = (from t in db.Profile where ids.Any(c => c == t.UserID) select t).ToList();
var ret = (from t in db.Profile where ids.Any(c => c == t.UserID) select t).ToList();
于是继续Goolge寻找第二种方法,在MSDN论坛上找一个构造Lambda语句的方法
替代方法2:构造Lambda语句
private
static
Expression
<
Func
<
TElement,
bool
>>
BuildWhereInExpression
<
TElement, TValue
>
(Expression
<
Func
<
TElement, TValue
>>
propertySelector, IEnumerable
<
TValue
>
values)
{
ParameterExpression p = propertySelector.Parameters.Single();
if ( ! values.Any())
return e => false ;
var equals = values.Select(value => (Expression)Expression.Equal(propertySelector.Body, Expression.Constant(value, typeof (TValue))));
var body = equals.Aggregate < Expression > ((accumulate, equal) => Expression.Or(accumulate, equal));
return Expression.Lambda < Func < TElement, bool >> (body, p);
}
{
ParameterExpression p = propertySelector.Parameters.Single();
if ( ! values.Any())
return e => false ;
var equals = values.Select(value => (Expression)Expression.Equal(propertySelector.Body, Expression.Constant(value, typeof (TValue))));
var body = equals.Aggregate < Expression > ((accumulate, equal) => Expression.Or(accumulate, equal));
return Expression.Lambda < Func < TElement, bool >> (body, p);
}
调用方法:
int
[] ids
=
new
int
[]{
10101
,
10005
,
10007
};
db.Profile.Where(BuildWhereInExpression < Profile, int > (v => v.Id,ids);
db.Profile.Where(BuildWhereInExpression < Profile, int > (v => v.Id,ids);
该方法可也扩展为:
public
static
IQueryable
<
TElement
>
WhereIn
<
TElement, TValue
>
(
this
IQueryable
<
TElement
>
source, Expression
<
Func
<
TElement, TValue
>>
propertySelector,
params
TValue[] values)
{
return source.Where(BuildWhereInExpression(propertySelector, values));
}
{
return source.Where(BuildWhereInExpression(propertySelector, values));
}
这样就可以直接使用下列方法调用
string
[] ids
=
new
string
[]{
10101
,
10005
,
10007
};
db.Profile.WhereNotIn(c => c.Id,ids);
db.Profile.WhereNotIn(c => c.Id,ids);
后来又看到网上有这样的解决办法
替代方法3:字符串构造
这个方法比较简单
string
[] ids
=
new
string
[]{
10101
,
10005
,
10007
};
string csvIds = string .Join( " , " , ids.Cast < string > ().ToArray());
db.Profile.Where( " it.Id in { " + csvIds + " } " );
string csvIds = string .Join( " , " , ids.Cast < string > ().ToArray());
db.Profile.Where( " it.Id in { " + csvIds + " } " );
it是什么这里就不用说了吧!