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

C# 使用实体框架创建动态查询,c#,linq,entity-framework,entity-framework-4,C#,Linq,Entity Framework,Entity Framework 4,我想知道使用实体框架和linq创建动态查询的最佳方法是什么 我想创建一个具有许多排序和筛选参数(超过50个)的服务。我将从gui中获取对象,这些将在其中填写。。。查询将从单个服务方法执行 我环顾四周,发现我可以动态创建一个字符串,该字符串可以在方法末尾执行。我不太喜欢这种方式。有更好的方法吗?最好使用compile check键入safe?您可以研究使用WCF数据服务创建服务,并动态创建URI以查询您的实体模型。我知道的唯一其他方法是基于您的筛选值构建IQueryable public

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

我想创建一个具有许多排序和筛选参数(超过50个)的服务。我将从gui中获取对象,这些将在其中填写。。。查询将从单个服务方法执行


我环顾四周,发现我可以动态创建一个字符串,该字符串可以在方法末尾执行。我不太喜欢这种方式。有更好的方法吗?最好使用compile check键入safe?

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

我知道的唯一其他方法是基于您的筛选值构建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();
        }
    }
公共列表获取(FilterValues筛选器)
{
使用(var context=new AdventureWorksEntities())
{
IQueryable query=context.Contacts.Where(c=>c.ModifiedDate>DateTime.Now);
如果(!string.IsNullOrEmpty(filter.FirstName))
{
query=query.Where(c=>c.FirstName==filter.FirstName);
}
如果(!string.IsNullOrEmpty(filter.LastName))
{
query=query.Where(c=>c.LastName==filter.LastName);
}
返回query.ToList();
}
}

您可以一步一步地编写一个
IQueryable
。假设您有一个
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;
}
public IQueryable GetQuery(过滤器定义过滤器)
{
IQueryable query=context.Set();
//假设在筛选器中未指定任何内容时返回所有记录
if(filter.FilterByName)
query=query.Where(t=>
t、 Name>=filter.NameFrom&&t.Name
t、 Quantity>=filter.QuantityFrom&&t.Quantity我创建了一个可以帮助您的。它支持统一的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);
//对已知字段进行筛选
var keyboard=Query.Create(p=>p.Category==“keyboard”);
var keyboards=repository.Get(键盘);
//或在动态字段上进行筛选
var filter=Query.Create(“评级”,OperationType.GreaterThan,4)
var filteredKeyboards=repository.Get(过滤器);
//您还可以将两个查询组合在一起
var filterdKeyboards2=repository.Get(keyboard.And(filter))
//在已知字段上订购
var orderedKeyboard=keyboard.OrderBy(o=>o.Asc(p=>p.Name));
var orderedKeyboards=repository.Get(orderedKeyboards);
//或在动态字段上按顺序排序
var userOrdering=keyboard.OrderBy(o=>o.Asc(“Name”);
var orderedKeyboards2=repository.Get(userOrdering);

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

谢谢,但这是如何工作的?这不是从数据库中提取所有数据,然后逐步执行吗tep将其缩小到所需的数据集???@t-edd:不,它利用了
延迟执行
()。这意味着上面示例中组成的
IQueryable
只是一个描述如何过滤数据的查询表达式。查询的实际执行根本不在示例中。您可以通过对
IQueryable
应用“贪婪”操作符来执行查询,例如
query.ToList()
。此时(而不是更早的时候),查询表达式被转换为SQL并发送到服务器。这不是很好,因为它假设
某个实体
具有名称和数量字段,所以这只是半动态的。有没有办法动态定义
呢?它也不允许动态条件可选运算符,例如,如果您希望动态地允许用户按“成本>10”或“成本<10”进行筛选,是的,但这是否有效的性能明智?何时执行select?最后调用ToList()时?假设我有非常大的数据集……不,这不是性能问题,因为它使用延迟执行只查询一次。