如何在实体框架中参数化查询

本文关键字:参数 查询 框架 实体 | 更新日期: 2023-09-27 18:03:10

我是EF的新手。我有一张项目列表表。我在我的软件中发现了一个查询,可以找到所有项目。

public Project[] FindAll()
{
    var projects = new List<Project>();
    using (var db = new ProjetDbConext())
    {
        var qProjects = from project in db.ProjectSet
            where project.CreateDateTime != null
            select project;
        projects = qProjects.ToList();
    }
    return projects.ToArray();
}

这似乎很好,但我不确定如何参数化它。我需要这个,因为我正在实现一个搜索功能,试图重用EF中的一些查询逻辑。

接受一个包含元组的List。每个元组基本上都有一个属性和一个搜索词列表。

。元组(FirstName, {Prasaanth,Bill};元组(LastName, {Neelakandan, Gates};

这意味着我需要写一个选择查询,我搜索项目,其中FirstName是Prasaanth或Bill。如果列表只有一个项

。元组(Company, {Microsoft};然后我只需要在我的查询中搜索一个where条件。

 public Project[] LoadSearchProjects(List<System.Tuple<string, List<string>>> searchTerms)
        {
            var projects = new List<Project>();
            using (var db = new ProjetDbConext())
            {
                foreach (System.Tuple<string, List<string>> pair in searchTerms)
                {
                    string attribute = pair.Item1;
                    List<string> terms = pair.Item2;
                      /// logic here
                 }  
            }
            return projects.ToArray();
        }

我总是可以写一个if条件:

if(attribute.equals("FirstName"){
 // query project.FirstName in the where conditon 

}

但是我要搜索的属性太多了。

我知道ADO。. NET方法:

 mycommands = new SqlCommand(" select projects from from Persons where '"+attibute+"' =  some search terms ... 

我不知道如何在我的EF查询中做这样的事情。

1)是否有一种方法EF允许我做动态属性的搜索?或者使用"+属性+"参数化??

2)我可以使用更好的数据结构来简化我的结构,而不是使用List<Tuple<string, List<string>> ?

3)我被建议使用第三方LINQKit或动态linq,但我不确定如何将其集成到EF查询。

如果这听起来像大学男生的代码,我很抱歉。如果还需要其他细节,请告诉我。

问候,Prasaanth

更新:按照Andriy的回答工作方法。我的问题是,如果我的数据库中的任何特定条目说Name是Null,这不起作用。

 private static Expression<Func<TEntity, bool>> BuildStringFilter<TEntity, TProp>(
            Tuple<string, List<string>> filter)
        {
          // entity is the Project table
            var entity = Expression.Parameter(typeof (TEntity));
            var prop = Expression.Property(entity, filter.Item1);
            //check if contains returns true
            var body = filter.Item2
                .Select(v => Expression.Equal(Expression.Call(prop,
                    typeof (String).GetMethod("Contains"),
                    new Expression[] { Expression.Constant(v) }), Expression.Constant(true)))
                .Aggregate(Expression.Or);

            var result = (Expression<Func<TEntity, bool>>) Expression.Lambda(body, entity);
            return result;
        }

我可以修改表达式,使Contains方法:

道具,typeof (String) .GetMethod("包含"),new Expression[] {Expression. constant (v)

如果属性(prop)的值为null

如何在实体框架中参数化查询

您可以使用代码片段:

public static Expression<Func<TEntity, bool>> BuildFilter<TEntity, TProp>(
    KeyValuePair<string, IEnumerable<TProp>> filter)
{
    var entity = Expression.Parameter(typeof(TEntity));
    var prop = Expression.Property(entity, filter.Key);
    var body = filter.Value
        .Select(v => Expression.Equal(prop, Expression.Constant(v)))
        .Aggregate((curr, next) => Expression.Or(curr, next));
    var result = (Expression<Func<TEntity, bool>>)Expression.Lambda(body, entity);
    return result;
}

并命名为:

var filter = new KeyValuePair<string, IEnumerable<string>> (
    "FirstName",
    new [] {"Alice", "Bob"}
);
var predicate = BuildFilter<Item, string>(filter);
var result = ctx.Items.Where(predicate);

另外,请参见如何:使用表达式树构建动态查询。

我在这里随便说说,但我认为像这样的东西会更简单:

public Project[] Find(Expression<Func<Project, bool> filter = null)
{    
    using (var db = new ProjetDbConext())
    {
        var query = db.ProjectSet.Where(p => p.CreateDateTime != null);
        if(filter != null)
            query = query.Where(filter);
       return query.ToArray();
    }
}

使用方式:

var projects = repo.Find(p => p.id > 100);