使用entity framework创builddynamic查询
我想知道什么是使用entity framework和LINQ创builddynamic查询的最佳方式。
我想创build一个服务,有许多参数sorting和过滤(超过50)。 我将从gui中获取对象,这些对象将被填充…并且将从单个服务方法执行查询。
我环顾四周我看到,我可以dynamic地创build一个string,可以在我的方法结束时执行。 我不太喜欢这种方式。 有没有更好的方法来做到这一点? 最好用编译检查键入安全吗?
你可以一步步IQueryable<T>
一个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; } }
…那么你可以build立一个像这样的查询:
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; }
我所知道的唯一的另一种方法是基于你的filter构build一个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(); } }
您可以使用dynamic规范和dynamicsorting。 我在这里和这里都有关于他们的博客。 下面的例子可以帮助你 –
//Assume you're getting following values from search form. string userSuppliedProperty = "AverageRating"; OperationType userSuppliedOperationType = OperationType.GreaterThan; var userSuppliedValue = 4.5; //Create DynamicSpecification from these properties and pass it to repository. var userFilter = new DynamicSpecification<Product>(userSuppliedProperty, userSuppliedOperationType, userSuppliedValue); var filteredProducts = _repository.Get(userFilter); //You can also combine two specifications using either And or Or operation string userSuppliedProperty2 = "Category"; OperationType userSuppliedOperationType2 = OperationType.EqualTo; var userSuppliedValue2 = "Keyboard"; var userFilter2 = new DynamicSpecification<Product>(userSuppliedProperty2, userSuppliedOperationType2, userSuppliedValue2); var combinedFilter = userFilter.And(userFilter2); var filteredProducts2 = _repository.Get(combinedFilter); //and it support dynamic sorting string userSuppliedOrderingProperty = "Category"; OrderType userSuppliedOrderType = OrderType.Ascending; var sortedFilteredProducts = _repository.Get(combinedFilter, o => o.InOrderOf(userSuppliedOrderingProperty, userSuppliedOrderType));
我不知道你得到的search对象/ DTO,但你可以很容易地创build一个通用search对象/ DTO,并可以用几行代码将其映射到GenericSpecification对象链。 过去我曾经用过WCF服务,它对我来说工作得非常好。
您可以考虑使用WCF数据服务创build服务,并dynamic创buildURI来查询您的实体模型。