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

时间:2018-02-05 11:13:49

标签: c# linq

我正在使用一行到sql查询创建一个实用程序,它将在数据网格中加载数据。

由于数据集超过80,000条记录,因此linq查询会处理过滤,以保持过滤掉UI线程。 我不能直接使用WPF中的过滤器过滤数据网格,因为应用过滤器很快就会处理UI线程,这会将窗口锁定过滤器需要应用的3分钟。

过滤选项由多个开关控制(功能为复选框),如果选中则返回bool。

我想使用这些开关来影响行查询,例如,如果选中已完成项目的选项,则对行查询的等效更改将是添加completed equals true作为where子句,但是如果他们没有被检查,我只是想忽略这个选项。

为了澄清,如果未选中显示已完成项目的复选框,我想显示所有项目是否已完成或未完成。 如果选中显示已完成项目的复选框,我想显示已完成的所有项目等于true。

目前,我正在以query的形式向名为query = query.Where(r => r.completed == true)的查询对象添加子句,但是这些需要包含在if语句中 - 我不能简单地将开关的值作为I如果交换机为false,则忽略过滤,而不是专门添加检查某个属性设置为false的条件。

作为linq的一部分提供了以这种方式实现变量行查询的任何内容,还是if阻止它的方式呢?

虽然这已被标记为可能的副本,但我不确定其他问题的解决方案是使用if语句,这是我希望避免的。 8年前也提出了这个问题,从那时起.NET平台发生了很大的变化。 我知道我可以使用多个if语句来处理这个问题,但是如果有更高效和/或更容易阅读的替代方案,我想使用它。

已经要求代码,

                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);
                }

这里的问题很简单,我有多个条款必须按特定顺序应用,即所有已批量完成的条目将在运行时删除所有未完成的项目。

我希望显示整个数据集,并且当且仅当选择了一个选项时,过滤掉与条件不匹配的任何内容。 我不想假设不检查框是否等同于假值。

由于有很多可选择的选项,我想知道是否有办法避免多个if语句 - 我并不是说我有问题,但是,在我没有发现有用的东西之前,我已经开始研究解决方案,并在有更好的答案时实施了一个巨大的解决方案。

1 个答案:

答案 0 :(得分:0)

本案例中适用于我的解决方案是使用Dynamic Expression API以字符串的形式(类似于SQL查询)形成查询,并以{{{{{{{{{{{ 1}}。

虽然表达式树是一个可用的解决方案,但这种形式不那么冗长,可读性更强,总体来说实现的工作量要少得多,并且允许将多个子句连接成一个query.Where("Status=hidden and BatchAgeDays>10");的调用。 / p>

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