简体   繁体   English

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

[英]Creating dynamic queries with entity framework

I would like to know what is the best way of creating dynamic queries with entity framework and linq. 我想知道使用实体框架和linq创建动态查询的最佳方法是什么。

I want to create a service that has many parameters for sorting and filtering (over 50). 我想创建一个具有许多用于排序和过滤的参数(超过50个)的服务。 I will be getting object from gui where these will be filled out... and query will be executed from a single service method. 我将从gui中获取对象,这些对象将被填写...并且查询将从单个服务方法执行。

I looked around And I saw that I could dynamically create a string that can be executed at the end of my method. 我环顾四周,发现可以动态创建一个可以在方法末尾执行的字符串。 I don't like this way very much. 我不太喜欢这种方式。 Is there a better way to do this? 有一个更好的方法吗? Preferably type safe with compile check? 最好输入带有编译检查的安全类型?

You could compose an IQueryable<T> step by step. 您可以逐步组成一个IQueryable<T> Assuming you have a FilterDefinition class which describes how the user wants to filter ... 假设您有一个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; }
}

... then you could build a query like so: ...那么您可以像这样建立查询:

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;
}

The only other way that I know of would be to build an IQueryable based on your filter 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();
        }
    }

I have created a generic repository which should help you. 我创建了一个通用的存储库 ,应该可以为您提供帮助。 It supports uniform API to query and sort on both known and dynamic fields: 它支持统一的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);

I do not know about the search object/DTO you're getting but you can easily create a generic search object/DTO and can map it to a Query object in few lines of code. 我不知道您要获得的搜索对象/ DTO,但是您可以轻松创建通用的搜索对象/ DTO,并可以用几行代码将其映射到Query对象。 I have used it in past around a WCF service and it has worked very well for me. 我过去在WCF服务中使用过它,对我来说效果很好。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM