简体   繁体   English

将多个变量where子句应用于linq查询

[英]Applying multiple variable where clauses to linq query

I am creating a utility using a line to sql query which will load data in a datagrid. 我正在使用到sql查询的行创建实用程序,该实用程序将在datagrid中加载数据。

As the data set is in excess of 80,000 records, filtering is handled by the linq query to keep the filtering off the UI thread. 由于数据集超过80,000条记录,因此linq查询将处理筛选,以使筛选保持在UI线程之外。 I cannot filter the data grid using a filter in WPF directly as applying the filter is handled soon the UI thread, which locks the window for the 3 minutes that the filter takes to apply. 我无法直接在WPF中使用过滤器来过滤数据网格,因为UI线程将立即处理该过滤器,从而将窗口锁定了3分钟(过滤器将要应用)。

The filtering options are controlled by a number of switches (the function as checkboxes), returning bool if checked. 过滤选项由许多开关(功能为复选框)控制,如果选中,则返回bool。

I want to use these switches to affect the line query, for example, if the option of completed items is checked, the equivalent change to the line query would be to add completed equals true as a where clause, however if they are not checked, I simply wish to ignore the option. 我想使用这些开关来影响行查询,例如,如果选中了完成项目选项,则对行查询的等效更改将是将completed equals true添加为where子句,但是,如果未选中它们,我只是希望忽略该选项。

To clarify, if the check box to show completed items is not checked, I want to show all items whether completed, or not completed. 为了澄清,如果未选中显示已完成项目的复选框,我想显示所有项目,无论已完成还是未完成。 If the check box to show completed items is checked, I want to show all items where completed is equal to true. 如果选中了显示已完成项目的复选框,那么我想显示已完成等于true的所有项目。

Currently, I am adding clauses to a query object called query in the form query = query.Where(r => r.completed == true) , however these need to be wrapped in an if statement - I cannot simply take the value of the switch as I want to ignore the filtering if the switch is false rather than specifically add a condition which checks a certain property is set to false. 当前,我正在将子句以query = query.Where(r => r.completed == true)的形式添加到名为query的查询对象中,但是这些query = query.Where(r => r.completed == true)需要包装在if语句中-我不能简单地采用开关,因为如果开关为假,我想忽略过滤,而不是专门添加检查某个属性设置为false的条件。

Is there anything provided as a part of linq for implementing a variable line query in this way, or is the if block the way to go about it? linq的一部分是否提供任何以这种方式实现可变行查询的内容,或者if阻止了它的实现?

Although this has been marked as a possible duplicate, I'm not certain that it is in that the solution to the other question is to use an if statement which is what I'm looking to avoid. 尽管已将其标记为可能的重复项,但我不确定这是因为另一个问题的解决方案是使用if语句,这是我要避免的内容。 That question was also asked over 8 years ago, and the .NET platform has changed a lot since then. 八年前,这个问题也被问到了。自那时以来,.NET平台发生了很大变化。 I'm aware that I can use multiple if statements to handle this, but if there is an alternative which is more efficient and/or easier to read, I'd like to use it. 我知道我可以使用多个if语句来处理此问题,但是如果有一个更有效和/或更易于阅读的替代方法,我想使用它。

As code has been asked for, 由于要求输入代码,

                IsBusy = true;
                String sqlConnect = connectionString;
                DbConnection connection = EFConnectionFactory.MakeConnection(sqlConnect);

                using (var db = new DbContext(connection)) {

                    var query = from l in db.Batch
                                join d in db.Document on l.id equals d.batch_id
                                group d by new { batchId = l.id, l.batchName, Added = l.added, Status = l.status, PaginationLocked = l.OKDate } into g
                                select new {
                                    BatchId = g.Key.batchId, BatchName = g.Key.batchName, CreatedDate = g.Min(t => t.added), g.Key.PaginationLocked, FinalisedDate = g.Max(t => t.OKDate), g
                                } into res
                                select new BatchChronologyDataModel {
                                    BatchId = res.BatchId,
                                    BatchName = res.BatchName,
                                    TotalDocuments = res.g.Count(),
                                    TotalOKayed = res.g.Where(s => s.documentOKayed != null).Count(),
                                    TotalExported = res.g.Where(s => s.editLocked != null).Count(),
                                    CreatedDate = res.g.Min(t => t.added),
                                    Status = res.g.Key.Status,
                                    PaginationLocked = res.PaginationLocked != null,
                                    FinalisedDate = res.g.Max(t => t.OKDate),
                                    DurationDays = DbFunctions.DiffDays(res.CreatedDate, res.FinalisedDate),
                                    BatchAgeDays = DbFunctions.DiffDays(res.CreatedDate, DateTime.Now),
                                    IsCompleted = res.g.Max(t => t.OKDate) != null,
                                };



                if (this.ShowLongCycleBatches) {
                    query = query.Where(r => r.DurationDays > 3);
                }

                if (this.Completed) {
                    query = query.Where(r => IsCompleted == true);
                }

The issue here is simply that I have multiple clauses which have to be applied in a certain order, ie all batched completed will remove all uncompleted items when it runs. 这里的问题很简单,我有多个子句必须按一定顺序应用,即所有批处理已完成的项目在运行时都将删除所有未完成的项目。

I wish to show the whole data set, and filter out anything which does not match the conditions if and only if an option is selected. 我希望显示整个数据集,并且仅当选择了一个选项时,才过滤掉不符合条件的所有内容。 I do not want to assume that not checking a box is equivalent to a false value. 我不想假设不选中一个框就等于一个假值。

As there are a lot of selectable options, I'd like to know if there is a way to avoid multiple if statements - I'm not saying that I have an issue with them, but I'd worked on solutions before where I've not spotted something useful and implemented a huge solution when there was a better answer. 由于有很多可选选项,因此我想知道是否有一种避免多条if语句的方法-我并不是说我对此有疑问,但是我在解决之前就已经研究过解决方案当找到更好的答案时,我没有发现有用的东西并实施了巨大的解决方案。

The solution in this case which worked for me was to use the Dynamic Expression API to form up a query in the form of a string (akin to an SQL query), and run this directly on the query in the form query.Where("Status=hidden and BatchAgeDays>10"); 在这种情况下,对我有用的解决方案是使用动态表达式API以字符串形式构成查询(类似于SQL查询),然后以查询形式直接在查询上运行query.Where("Status=hidden and BatchAgeDays>10"); .

Although expression trees would be a usable solution, this form is less verbose and more readable, and overall a great deal less work to implement, and allows multiple clauses to be concatenated into a single call to Where . 尽管表达式树将是一个可用的解决方案,但这种形式的详细程度较低,可读性更高,总体上实现起来工作量也少得多,并且允许将多个子句合并为对Where的单个调用。

https://github.com/kahanu/System.Linq.Dynamic/wiki/Dynamic-Expressions https://github.com/kahanu/System.Linq.Dynamic/wiki/Dynamic-Expressions

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

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