如何使用附加参数更新Linq表达式?我有一个Linq表达式,它可能会根据某些条件发生变化。我想做的一个例子(留一点空白我不确定):Expressionfilter=(Projectp)=>p.UserName=="Bob";if(showArchived){//更新过滤器以添加&&p。归档}//过滤器构建时查询数据库IEnumerableprojects=unitOfWork.ProjectRepository.Get(filter);如何更新过滤器以添加任何额外参数?在检索所有记录的那一刻,我使用Where进一步过滤结果。但是,这会导致对数据库的查询比绝对必要的多。IEnumerableprojects=unitOfWork.ProjectRepository.Get(filter);如果(showArchived){projects=projects.Where(p=>p.Archived);}Get方法使用GenericRepository模式:publicclassGenericRepositorywhereTEntity:class{internalProgrammeDBContextcontext;内部DbSetdbSet;publicGenericRepository(ProgrammeDBContextcontext){this.context=context;this.dbSet=context.Set();}publicvirtualIEnumerableGet(Expressionfilter=null,FuncorderBy=null,stringincludeProperties=""){IQueryablequery=dbSet;如果(过滤器!=null){query=query.Where(过滤器);}foreach(varincludePropertyinincludeProperties.Split(newchar[]{','},StringSplitOptions.RemoveEmptyEntries)){query=query.Include(includeProperty);}if(orderBy!=null){returnorderBy(query).ToList();}else{returnquery.ToList();}}publicvirtualTEntityGetByID(objectid){returndbSet.Find(id);}公共空间tualvoidInsert(TEntityentity){dbSet.Add(entity);}publicvirtualvoidDelete(objectid){TEntityentityToDelete=dbSet.Find(id);删除(实体删除);}publicvirtualvoidDelete(TEntityentityToDelete){if(context.Entry(entityToDelete).State==EntityState.Detached){dbSet.Attach(entityToDelete);}dbSet.Remove(entityToDelete);}publicvirtualvoidUpdate(TEntityentityToUpdate){dbSet.Attach(entityToUpdate);context.Entry(entityToUpdate).State=EntityState.Modified;}publicvirtualIEnumerableGetWithRawSql(stringquery,paramsobject[]parameters){returndbSet.SqlQuery(query,parameters).ToList();}}更新根据MarcGravell和DavidB的下面代码创建了一些扩展方法,为我解决了这个问题组合或();}publicstaticExpressionCombineOr(thisIEnumerable>filters){if(!filters.Any()){ExpressionalwaysTrue=x=>true;总是返回真;}表达式firstFilter=filters.First();varlastFilter=firstFilter;表达式结果=null;foreach(varnextFilterinfilters.Skip(1)){varnextExpression=newReplaceVisitor(lastFilter.Parameters[0],nextFilter.Parameters[0]).Visit(lastFilter.Body);结果=Expression.Lambda(Expression.OrElse(nextExpression,nextFilter.Body),nextFilter.Parameters);最后一个过滤器=下一个过滤器;}返回结果;}publicstaticExpressionCombineAnd(paramsExpression[]filters){returnfilters.CombineAnd();}publicstaticExpressionCombineAnd(thisIEnumerable>filters){if(!filters.Any()){ExpressionalwaysTrue=x=>true;总是返回真;}表达式firstFilter=filters.First();varlastFilter=firstFilter;表达式重新结果=空;foreach(varnextFilterinfilters.Skip(1)){varnextExpression=newReplaceVisitor(lastFilter.Parameters[0],nextFilter.Parameters[0]).Visit(lastFilter.Body);结果=Expression.Lambda(Expression.AndAlso(nextExpression,nextFilter.Body),nextFilter.Parameters);最后一个过滤器=下一个过滤器;}返回结果;}classReplaceVisitor:ExpressionVisitor{privatereadonlyExpressionfrom,to;publicReplaceVisitor(Expressionfrom,Expressionto){this.from=from;这个.to=to;}publicoverrideExpressionVisit(Expressionnode){returnnode==from?到:base.Visit(节点);如果我理解这个问题,那么很可能是问题所在:IEnumerableprojects=unitOfWork.ProjectRepository.Get(filter);项目上的任何工作都将使用Enumerable,而不是Queryable;它可能应该是:IQueryableprojects=unitOfWork.ProjectRepository.Get(filter);如果(showArchived){projects=projects.Where(p=>p.Archived);后者是可组合的,并且.Where应该按预期工作,在将其发送到服务器之前构建更严格的查询您的另一个选择是在发送之前覆盖要合并的过滤器:usingSystem;使用System.Linq.Expressions;静态类程序{staticvoidMain(){表达式>filter1=x=>xA>1;表达式>filter2=x=>xB>2.5;//组合两个谓词://需要重写其中一个lambda,交换另一个varrewrittenBody1=newReplaceVisitor(filter1.Parameters[0],filter2.Parameters[0]).Visit(filter1.Body);varnewFilter=Expression.Lambda>(Expression.AndAlso(rewrittenBody1,filter2.Body),filter2.Parameters);//newFilter等价于:x=>xA>1&&xB>2.5}}classFoo{publicintA{get;放;}公共浮动B{得到;放;}}classReplaceVisitor:ExpressionVisitor{privatereadonlyExpressionfrom,to;publicReplaceVisitor(Expressionfrom,Expressionto){this.from=from;这个.to=to;}publicoverrideExpressionVisit(Expressionnode){returnnode==from?到:base.Visit(节点);或以方便的方式覆盖:usingSystem;使用系统tem.Linq.表达式;staticclassProgram{staticvoidMain(){Expression>filter=x=>xA>1;boolapplySecondFilter=true;如果(applySecondFilter){filter=Combine(过滤器,x=>xB>2.5);}vardata=repo.Get(过滤器);}staticExpression>Combine(Expression>filter1,Expression>filter2){//组合两个谓词://需要重写其中一个lambda,交换另一个varrewrittenBody1=newReplaceVisitor(filter1.Parameters[0],filter2.Parameters[0]).Visit(filter1.Body);varnewFilter=Expression.Lambda>(Expression.AndAlso(rewrittenBody1,filter2.Body),filter2.Parameters);返回新过滤器;}}classFoo{publicintA{get;放;}公共浮动B{得到;放;}}classReplaceVisitor:ExpressionVisitor{privatereadonlyExpressionfrom,to;publicReplaceVisitor(Expressionfrom,Expressionto){this.from=from;这个.to=to;}publicoverrideExpressionVisit(Expressionnode){returnnode==from?吨o:base.Visit(node);我认为您想以这种方式组合过滤器:varmyFilters=newList>>();myFilters.Add(c=>c.Name.StartsWith("B"));myFilters.Add(c=>c.Orders.Count()==3);如果(搁浅){myFilters.Add(c=>c.Friends.Any(f=>f.Cars.Any()));//朋友有车}Expression>filter=myFilters.AndTheseFiltersTogether();IEnumerablethoseCustomers=Data.Get(filter);此代码将允许您组合过滤器publicstaticExpression>OrTheseFiltersTogether(paramsExpression>[]filters){returnfilters.OrTheseFiltersTogether();}}publicstaticExpression>OrTheseFiltersTogether(thisIEnumerable>>filters){if(!filters.Any()){Expression>alwaysTrue=x=>true;总是返回真;表达式>firstFilter=filters.First();varbody=firstFilter.Body;varparam=firstFilter.Parameters.ToArray();foreach(varnextFilterinfilters.Skip(1)){varnextBody=Expression.Invoke(nextFilter,param);body=Expression.OrElse(body,nextBody);}表达式>结果=表达式.Lambda>(正文,参数);返回结果;}publicstaticExpression>AndTheseFiltersTogether(paramsExpression>[]filters){returnfilters.AndTheseFiltersTogether();}publicstaticExpression>AndTheseFiltersTogether(thisIEnumerable>>filters){if(!filters.Any()){Expression>alwaysTrue=x=>true;总是返回真;表达式>firstFilter=filters.First();varbody=冷杉tFilter.Body;varparam=firstFilter.Parameters.ToArray();foreach(varnextFilterinfilters.Skip(1)){varnextBody=Expression.Invoke(nextFilter,param);body=Expression.AndAlso(body,nextBody);}表达式>结果=表达式.Lambda>(正文,参数);返回结果;这完全取决于ProjectRepository.Get()的行为方式和返回的内容通常的方式(例如,LINQtoSQL执行类似的操作)是它返回一个IQueryable并允许您(除其他外)添加更多Where()在将查询以SQL形式发送到服务器之前添加查询的子句,其中包含所有Where()子句。如果是这种情况,Mark的解决方案(使用IQuerybale)将为您工作。但是如果Get()方法立即执行基于过滤器的查询,则需要将表达式中的整个过滤器传递给它。为此,您可以使用PredicateBuilder。如果Get方法检索数据并将其返回到内存中的对象中,您可以这样做Expressionfilter=(Projectp)=>p.UserName=="Bob";if(showArchived){filter=(Projectp)=>p.UserName=="Bob"&&p.Archived;}IEnumerableprojects=unitOfWork.ProjectRepository.Get(filter);编辑只是为了指出。当您使用.ToList()方法时,它会枚举Queryable,即发出数据库请求。摆脱ToList(),你会没事的。以上就是C#学习教程:Linq表达式如何更新其他参数?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: