LINQ to Entities 实现sql 关键字"In"方式总结

转自:http://kb.cnblogs.com/a/1527224/

http://www.cnblogs.com/ejiyuan/

 

方法1 比较局限(未深究的结论), 只适用于 in ObjectQuery<T> where T:Entity,换做 IEnumerable<T>(往往我们需要从Silverlight端传IEnumerable<T>到Server端),便会提示如下错误:

base {System.SystemException} = {"Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."}

方法2 很受用

方法3 Where:ObjectQurey.Where

 

原文如下:

在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();

 

替代方法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();

使用方法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();

于是继续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);
        }

调用方法:

int [] ids  =   new   int []{ 10101 , 10005 , 10007 };
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));
        }

这样就可以直接使用下列方法调用

string [] ids  =   new   string []{ 10101 , 10005 , 10007 };
db.Profile.WhereIn(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 + " } " );

it是什么这里就不用说了吧!

 

你可能感兴趣的:(LINQ)