Entity framework 实体框架构建或传递到何处

Entity framework 实体框架构建或传递到何处,entity-framework,lambda,where,func,Entity Framework,Lambda,Where,Func,我想知道我该怎么做? 事实上,我有一个具有搜索条件的对象(一些要搜索的字段,这意味着条件)。我需要根据条件构建查询,但它使用和连接where。 这就是我所拥有的: public class SearchCriteria { public SearchCriteria() { this.Theme = new HashSet<int>(); } public string KeyWord { get; set; } public

我想知道我该怎么做? 事实上,我有一个具有搜索条件的对象(一些要搜索的字段,这意味着条件)。我需要根据条件构建查询,但它使用和连接where。 这就是我所拥有的:

public class SearchCriteria
{
    public SearchCriteria()
    {
        this.Theme = new HashSet<int>();
    }

    public string KeyWord { get; set; }
    public bool? ChildrenFirstCycle  { get; set; }
    public bool? ChildrenSecondCycle { get; set; }
    public bool? Primary { get; set; }
    public bool? Secondary { get; set; }
    public bool? BachelorArts { get; set; }
    public bool? BachelorHumanities { get; set; }
    public bool? BachelorScience { get; set; }
    public bool? University { get; set; }
    public bool? MediumLevelCycle { get; set; }
    public bool? HighLevelCycle { get; set; }
    public int? DistrictID { get; set; }
    public int? CountyID { get; set; }
    public int? MunicipalID { get; set; }
    public ICollection<int> Theme { get; set; }
}

    public IEnumerable<School> GetAllEscuelasBySearchCriteria(SearchCriteria searchCriteria)
    {
        var Query = this._repository.Retrieve();

        if (!string.IsNullOrWhiteSpace(searchCriteria.KeyWord))
        {
            Query = Query.Where(p => p.Name.Contains(searchCriteria.KeyWord) || p.Grade.Contains(searchCriteria.KeyWord) || p.Email.Contains(searchCriteria.KeyWord) || p.Address.Contains(searchCriteria.KeyWord) || p.Code.Contains(searchCriteria.KeyWord));
        }

        //Rest of condition
        if (RestConditions)
        {
            Query = Query.Where(p=> REST CONDITIONS);
        }

        //I need to create a list of func expression and add each expression pass the condition and then a foreach and do an OR for all in List of FUNC

        if (searchCriteria.InfantilFirstCycle.HasValue && searchCriteria.InfantilFirstCycle.Value != false)
        {
            Query = Query.Where(p => (p.value1 > 0 || p.value2 > 0 || p.value3 > 0));
        }
        if (searchCriteria.InfantilSecondCycle.HasValue && searchCriteria.InfantilSecondCycle.Value != false)
        {
            Query = Query.Where(p => (p.value4 > 0 || p.value5 > 0 || p.value6 > 0));
        }
        if (searchCriteria.Primary.HasValue && searchCriteria.Primary.Value != false)
        {
            Query = Query.Where(p => (p.value7 > 0 || p.value8 > 0 || p.value9 > 0 || p.value10 > 0 || p.value11 > 0 || p.value13 > 0 || p.value14 > 0));
        }

        return Query.Distinct().OrderBy(c=>c.Name).ToList();
    }
公共类搜索条件
{
公共搜索标准()
{
this.Theme=newhashset();
}
公共字符串关键字{get;set;}
公共bool?ChildrenFirstCycle{get;set;}
公共bool?ChildrenSecondCycle{get;set;}
公共布尔?主{get;set;}
公共布尔?次{get;set;}
公共布尔?单身汉{get;set;}
公共布尔?单身汉{get;set;}
公共布尔?学士学位{get;set;}
公立学校?大学{get;set;}
public bool?MediumLevelCycle{get;set;}
public bool?HighLevelCycle{get;set;}
公共int?DistrictID{get;set;}
公共int?CountyID{get;set;}
公共int?市政许可证{get;set;}
公共ICollection主题{get;set;}
}
public IEnumerable GetAllesCellasbySearchCriteria(搜索条件搜索条件)
{
var Query=this._repository.Retrieve();
如果(!string.IsNullOrWhiteSpace(searchCriteria.KeyWord))
{
Query=Query.Where(p=>p.Name.Contains(searchCriteria.KeyWord)| p.Grade.Contains(searchCriteria.KeyWord)| p.Email.Contains(searchCriteria.KeyWord)| p.Code.Contains(searchCriteria.KeyWord));
}
//其余情况
if(rest条件)
{
Query=Query.Where(p=>REST条件);
}
//我需要创建一个func表达式列表,并添加每个表达式,然后通过条件和foreach,并在func列表中对所有表达式执行OR
if(searchCriteria.infantialFirstCycle.HasValue&&searchCriteria.infantialFirstCycle.Value!=false)
{
Query=Query.Where(p=>(p.value1>0 | | p.value2>0 | | p.value3>0));
}
if(searchCriteria.infantalSecondCycle.HasValue&&searchCriteria.infantalSecondCycle.Value!=false)
{
Query=Query.Where(p=>(p.value4>0 | | p.value5>0 | | p.value6>0));
}
if(searchCriteria.Primary.HasValue&&searchCriteria.Primary.Value!=false)
{
Query=Query.Where(p=>(p.value7>0 | | p.value8>0 | | p.value9>0 | | p.value10>0 | | p.value11>0 | p.value13>0 | p.value14>0));
}
返回Query.Distinct().OrderBy(c=>c.Name.ToList();
}

查看此nuget软件包在IQueryable上启用搜索扩展

它将允许您执行以下操作:

var query = this._repository.Retrieve();

query = query.Search(searchCriteria.KeyWord, p => p.Name, p => p.Email, p => p.Address, p => p.Code)
             .Where(p => searchCriteria.InfantilFirstCycle == true && (p.value1 > 0 || p.value2 > 0 || p.value3 > 0))
             .Where(p => searchCriteria.InfantilSecondCycle == true && (p.value4 > 0 || p.value5 > 0 || p.value6 > 0))
             .Where(p => searchCriteria.Primary == true && (p.value7 > 0 || p.value8 > 0 || p.value9 > 0 || p.value10 > 0 || p.value11 > 0 || p.value13 > 0 || p.value14 > 0))

return query.Distinct().OrderBy(c=>c.Name).ToList();
这里提供了源代码以及一些示例用法:

对于附加的where子句,您可以调整searchextensions代码以满足您的需要。类似下面的内容将启用以下语法:

    var query = this._repository.Retrieve();    
    query = query.Search(searchCriteria.KeyWord, 
                         p => p.Name, 
                         p => p.Email, 
                         p => p.Address, 
                         p => p.Code)

    if(searchCriteria.InfantilFirstCycle == true)
    {
        query = query.IntGreaterThan(0, p => p.value1, p => p.value2, p => p.value3);            
    }

    if(searchCriteria.InfantilSecondCycle == true)
    {
        query = query.IntGreaterThan(0, p => p.value4, p => p.value5, p => p.value6);            
    }

    if(searchCriteria.Primary == true)
    {
        query = query.IntGreaterThan(0, p => p.value7, p => p.value8, p => p.value9, p => p.value10, p => p.value11, p => p.value13, p => p.value14);
    }

    return query.Distinct().OrderBy(c=>c.Name).ToList(); 
下面是启用上述功能的代码。(请注意,这是未经测试编写的,可能需要调整)

公共静态类扩展
{
公共静态IQueryable IntGreaterThan(此IQueryable源,int greaterThanValue,参数表达式[]integerProperties)
{
//用于保存合并的“或”表达式的变量
表达式orExpression=null;
//检索第一个参数以使用accross all表达式
var singleParameter=integerProperties[0]。Parameters.Single();
//创建一个常量来表示搜索词
ConstantExpression greaterThanExpression=表达式.常量(greaterThanValue)
//为每个属性生成一个包含表达式
foreach(IntegerProperty中的变量intProperty)
{
//跨每个属性同步单个参数
var swappedParamExpression=SwapExpressionVisitor.Swap(intProperty,intProperty.Parameters.Single(),singleParameter);
//生成表达式以表示x.[propertyX]>greaterThanValue
var expression=BuildGreaterThanExpression(交换参数表达式,greaterThanExpression);
//将contains expresion添加到现有表达式
orExpression=BuildOrExpression(orExpression,expression);
}     
var completeExpression=Expression.Lambda(orExpression,singleParameter);
返回source.Where(completeExpression);
}
私有静态二进制表达式BuildGreaterThanExpression(Expression intProperty,ConstantExpression greaterThanExpression)
{
返回表达式.GreaterThan(intProperty.Body,greaterThanExpression);
}
/// 
///使用OrElse表达式连接到表达式
/// 
私有静态表达式BuildOrExpression(表达式existingExpression、表达式expressionToAdd)
{
if(existingExpression==null)
{
返回要添加的表达式;
}
//为每个属性生成“或”表达式
返回表达式.OrElse(existingExpression,expressionToAdd);
}
}
内部类SwapExpressionVisitor:ExpressionVisitor
{
私有只读表达式from、to;
私人SwapExpressionVisitor(表达式从,表达式到)
{
这个@from=@from;
这个;
}
公共静态表达式交换(表达式lambda、表达式from、表达式to)
{
返回表达式.Lambda(
交换(lambda.Body、from、to)、lambda.Parameters);
}
专用静态表达式交换(表达式体、表达式从、表达式到)
{
返回新的SwapExpressionVisitor(从、到)。访问(正文);
}
公共重写表达式访问(表达式节点)
{
return node==this.@from?this.to:base.Visit(节点);
}
}    

我遇到了这个问题,最终使用了动态linq。我尝试过,但说base{System.Exception}={“linq to Entities中不支持linq表达式节点类型‘Invoke’。}这正是我想要的。A.
public static class Extensions
{
    public static IQueryable<T> IntGreaterThan<T>(this IQueryable<T> source, int greaterThanValue, params Expression<Func<T, int>>[] integerProperties)
    {
        //Variable to hold merged 'OR' expression
        Expression orExpression = null;

        //Retrieve first parameter to use accross all expressions
        var singleParameter = integerProperties[0].Parameters.Single();

        //Create a constant to represent the search term
        ConstantExpression greaterThanExpression = Expression.Constant(greaterThanValue)

        //Build a contains expression for each property
        foreach (var intProperty in integerProperties)
        {
            //Syncronise single parameter accross each property
            var swappedParamExpression = SwapExpressionVisitor.Swap(intProperty, intProperty.Parameters.Single(), singleParameter);

            //Build expression to represent x.[propertyX] > greaterThanValue
            var expression = BuildGreaterThanExpression(swappedParamExpression, greaterThanExpression);

            //Add contains expresion to the existing expression
            orExpression = BuildOrExpression(orExpression, expression);
        }     

        var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, singleParameter);
        return source.Where(completeExpression);
    }

    private static BinaryExpression BuildGreaterThanExpression<T>(Expression<Func<T, int>> intProperty, ConstantExpression greaterThanExpression)
    {
        return Expression.GreaterThan(intProperty.Body, greaterThanExpression);
    }

    /// <summary>
    /// Connect to expressions using the OrElse expression
    /// </summary>
    private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
    {
        if (existingExpression == null)
        {
            return expressionToAdd;
        }

        //Build 'OR' expression for each property
        return Expression.OrElse(existingExpression, expressionToAdd);
    }
}


internal class SwapExpressionVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    private SwapExpressionVisitor(Expression from, Expression to)
    {
        this.@from = @from;
        this.to = to;
    }

    public static Expression<T> Swap<T>(Expression<T> lambda, Expression from, Expression to)
    {
        return Expression.Lambda<T>(
            Swap(lambda.Body, from, to), lambda.Parameters);
    }

    private static Expression Swap(Expression body, Expression from, Expression to)
    {
        return new SwapExpressionVisitor(from, to).Visit(body);
    }

    public override Expression Visit(Expression node)
    {
        return node == this.@from ? this.to : base.Visit(node);
    }
}