我想知道使用实体框架和linq创建动态查询的最佳方法是什么。
我想创建一个服务,它有许多用于排序和过滤的参数(超过50个)。我将从gui获取这些将被填写的对象...并且查询将从单个服务方法执行。
我环顾四周而且我看到我可以动态创建一个可以在方法结束时执行的字符串。我不太喜欢这种方式。有一个更好的方法吗?最好是带编译检查的类型安全吗?
答案 0 :(得分:54)
您可以逐步撰写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 :(得分:32)
我所知道的另一种方法是根据你的过滤器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();
}
}
答案 2 :(得分:6)
我创建了generic repository,可以帮到你。它支持统一的API来查询和排序已知和动态字段:
<!--[if IE 8]>
According to the conditional comment this is IE 8<br />
<![endif]-->
我不知道您正在获取的搜索对象/ DTO,但您可以轻松创建通用搜索对象/ DTO,并可以在几行代码中将其映射到Query对象。我过去在WCF服务中使用它,它对我来说非常好。
答案 3 :(得分:1)
您可以考虑使用WCF数据服务创建服务,并动态创建URI以查询您的实体模型。