首页 文章

使用实体框架创建动态查询

提问于
浏览
35

我想知道使用实体框架和linq创建动态查询的最佳方法是什么 .

我想创建一个服务,它有很多参数用于排序和过滤(超过50) . 我将从gui获取对象,其中将填写这些对象...并且将从单个服务方法执行查询 .

我环顾四周然后看到我可以动态创建一个可以在方法结束时执行的字符串 . 我不太喜欢这种方式 . 有一个更好的方法吗?最好是带编译检查的类型安全?

4 回答

  • 6

    我所知道的另一种方法是根据你的过滤器vaues构建一个IQueryable .

    public List<Contact> Get(FilterValues filter)
        {
            using (var context = new AdventureWorksEntities())
            {
                IQueryable<Contact> query = context.Contacts.Where(c => c.ModifiedDate > DateTime.Now);
    
                if (!string.IsNullOrEmpty(filter.FirstName))
                {
                    query = query.Where(c => c.FirstName == filter.FirstName);
                }
    
                if (!string.IsNullOrEmpty(filter.LastName))
                {
                    query = query.Where(c => c.LastName == filter.LastName);
                }
    
                return query.ToList();
            }
        }
    
  • 52

    你可以一步一步地组成一个 IQueryable<T> . 假设你有一个 FilterDefinition 类来描述用户想要如何过滤...

    public class FilterDefinition
    {
        public bool FilterByName { get; set; }
        public string NameFrom { get; set; }
        public string NameTo { get; set; }
    
        public bool FilterByQuantity { get; set; }
        public double QuantityFrom { get; set; }
        public double QuantityTo { get; set; }
    }
    

    ...然后你可以像这样构建一个查询:

    public IQueryable<SomeEntity> GetQuery(FilterDefinition filter)
    {
        IQueryable<SomeEntity> query = context.Set<SomeEntity>();
        // assuming that you return all records when nothing is specified in the filter
    
        if (filter.FilterByName)
            query = query.Where(t => 
                t.Name >= filter.NameFrom && t.Name <= filter.NameTo);
    
        if (filter.FilterByQuantity)
            query = query.Where(t => 
                t.Quantity >= filter.QuantityFrom && t.Quantity <= filter.QuantityTo);
    
        return query;
    }
    
  • 1

    我创建了一个generic repository,它可以帮到你 . 它支持统一的API来查询和排序已知和动态字段:

    //Filter on known fields
           var keyboard = Query<Product>.Create(p=>p.Category=="Keyboard");
           var keyboards = repository.Get(keyboard);
    
           //Or filter on dynamic fields
           var filter = Query<Product>.Create("Rating", OperationType.GreaterThan, 4)
           var filteredKeyboards = repository.Get(filter);
    
           //You can also combine two queries togather
           var filterdKeyboards2 = repository.Get(keyboard.And(filter))
    
           //Order it on known fields
           var orderedKeyboard = keyboard.OrderBy(o=>o.Asc(p=>p.Name));
           var orderedKeyboards = repository.Get(orderedKeyboard);
    
           //Or order by on dynamic fields
           var userOrdering = keyboard.OrderBy(o=>o.Asc("Name"));
           var orderedKeyboards2 = repository.Get(userOrdering);
    

    我不知道您正在获取的搜索对象/ DTO,但您可以轻松创建通用搜索对象/ DTO,并可以在几行代码中将其映射到Query对象 . 我过去在WCF服务中使用它,它对我来说非常好用 .

  • 31

    您可以考虑使用WCF数据服务创建服务,并动态创建URI以查询实体模型 .

相关问题