有没有办法在没有数据源的情况下将LINQ查询创建为变量? [英] Is there any way to create a LINQ query as a variable without having the data source (yet)?
问题描述
Preamble:
My core question is very similar to this one: How can I write a clean Repository without exposing IQueryable to the rest of my application? which has remained unanswered. I am hoping that if I approach the problem in a different way, and ask a slightly different question, I may get a result. I will repeat some of the content from this other question to avoid requiring readers to read it for context.
问题:
我正在使用POCO实体和Entity Framework4.我试图允许在应用程序层对实体集进行复杂的即席过滤,同时尝试避免暴露IQueryable<T>
超出我的存储库边界.这给我带来了一些麻烦.
Problem:
I'm working with POCO entities, and Entity Framework 4. I am trying to allow for sophisticated ad-hoc filtering of entity sets at the application layer, while simultaneously trying to avoid exposing IQueryable<T>
past my repository boundary. This is leaving me with some complications.
-
我不想在需要大量参数的存储库上创建单个大型过滤器方法,例如:
I do not want to create a single massive filter method on the repository that takes a huge list of parameters, such as:
IEnumerable GetFilteredCustomers(string nameFilter, string addressFilter, bool isActive, int customerId, ...)
不仅使用起来非常麻烦,而且看起来也很丑陋,特别是如果它主要是一堆null,等等.它也没有我想要的可维护性.
Not only is this extremely cumbersome to use, but it's super ugly to look at, especially if it's mostly a bunch of nulls, etc. It's also not as maintainable as I would like.
我不想在存储库上创建大量过滤方法,例如:
I do not want to create a huge set of filter methods on the repository, such as:
IEnumerable GetActiveCustomers()
IEnumerable GetCustomersByName()
此方法存在很多问题,包括需要大量方法扩展到n!
,如果我希望能够以任意方式组合它们,则n是可用过滤条件的数量. (即名称为George的所有活跃客户).也很难维护.
There are a number of problems with this approach, including needing a huge list of methods which grows to n!
where n is the number of available filter conditions if I want to be able to combine them in arbitrary ways. (i.e. all active customers with name George). Also highly difficult to maintain.
我不想创建操纵IEnumerable<T>
的可链接方法(Fluent接口),因为最终这涉及从数据库中获取巨大的结果集并将其过滤到内存中,这不是可扩展的解决方案.
I do not want to create chainable methods (Fluent Interface) that manipulate IEnumerable<T>
, because ultimately that involves bringing back a huge result set from the database and filtering it down in-memory which is not a scalable solution.
我无法创建操纵IQueryable<T>
的Fluent接口,因为正如我已经说过的那样,我不想在存储库之外公开IQueryable<T>
.
I can't create a Fluent Interface that manipulates IQueryable<T>
because as I've already said, I don't want to expose the IQueryable<T>
past the repositories.
我想避免通过传入一个充满参数的对象(而不是大参数列表)来简单地重新哈希单个大规模过滤器方法,尽管此时这可能是最丑陋的解决方案.
I'd like to avoid simply rehashing the single massive filter method by passing in an object full of parameters instead of a large parameter list, although at this point this might be the least ugly solution.
想法:
最终,我认为理想的解决方案是找到某种方法来创建不知道源的完整查询,并将其存储为参数.然后,我可以将其传递到已知源的存储库中,并将查询应用于源并返回结果.
Ideas:
Ultimately, I think an ideal solution would be discovering some way to create a full query that doesn't know the source, and store it as a parameter. I could then pass that into the repository, where the source is known, and apply the query to the source and return the results.
澄清;与如上所述简单地创建参数对象相反,我想使用原始的LINQ查询,但是以某种方式将它们存储在变量中,然后将它们应用于数据源.我怀疑必须提前知道返回类型,但是我很好地定义了它并事先知道了.
To clarify; in contrast to simply creating an object of parameters as mentioned above, I'd like to use the raw LINQ queries, but store them in a variable somehow, and apply them to a data source later. I suspect the return type would have to be known ahead of time, but I'm perfectly fine with defining that and having it known in advance.
要从另一个角度查看它,请考虑以下事项:
To view it from yet another perspective, consider the following:
IQueryable<Customer> filteredCustomers = customerRepository.GetAll()
.Where(c => c.FirstName == "Dave")
.Where(c => c.IsActive == true)
.Where(c => c.HasAddress == true)
;
我想将三个Where子句打包为一个查询对象,与customerRepository.GetAll()完全分开,将其作为参数传递并在以后应用.
I want to package up the three Where clauses as a query object, completely separate from the customerRepository.GetAll(), pass it around as a parameter and apply it later.
推荐答案
好的.您可以编写如下方法:
Sure. You can write a method like:
public Expression<Func<Customer, bool>> GetDave()
{
return c => c.FirstName == "Dave"
&& c.IsActive
&& c.HasAddress;
}
...以及类似的存储库方法:
...and repository methods like:
public IEnumerable<Customer> GetOneGuy(Expression<Func<Customer, bool>> criteria)
{
return Context.Customers.Where(criteria);
}
...并致电:
var dave = Repository.GetOneGuy(this.GetDave()).Single();
这篇关于有没有办法在没有数据源的情况下将LINQ查询创建为变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!