执行不良的查询需要重写

本文关键字:重写 查询 不良 执行 | 更新日期: 2023-09-27 18:00:23

我有一段代码执行不好,需要重新编写它,以便在启动.ToList之前引入一个适当的where子句。然而,这就是我遇到的问题。

目前代码看起来像这样(大致上,我已经去掉了一些搜索标准,使其更容易显示)

var Widgets = from b in _caspEntities.Widgets.Include("WidgetRegionLogs")
                    .Include("WidgetStatusLogs").Include("WidgetVoltageTests")
                        select b;
IEnumerable<Widget> results = Widgets.ToList();
if (comboBoxRegion.SelectedValue.ToString() != "0")
{
    results = from b in results
              where b.CurrentRegionLog != null && b.CurrentRegionLog.RegionId == int.Parse(comboBoxRegion.SelectedValue.ToString())
              select b;
}
if (comboBoxStatus.SelectedValue != null)
{
    results = from b in results
              where b.CurrentStatusLog != null && b.CurrentStatusLog.StatusId == comboBoxStatus.SelectedValue.ToString()
              select b;
}
if (txtCode.Text.Trim().Length > 0)
{
    results = from b in results
              where b.CodeNumber == txtCode.Text.Trim()
              select b;
}
dataGridViewWidget.DataSource = results.ToList();

我可以很容易地编写SQL,本质上模型很简单,我有一个Widget,它有一个RegionLog和一个StatusLog,两者都存储历史。通过按WidgetID分组并选择最近的更新日期(然后转到region和status表以获得实际值),可以从中检索当前区域和状态。

所以,我需要把这个翻译成LINQ,但说实话,我不知道,但我很愿意学习。在我的脑海中,我认为我需要添加一些更好的where子句,然后在应用了where子句后执行Widget.toList。我很难理解CurrentRegionLogCurrentStatusLog的概念,因为在运行IEnumerable之前,它们不会被填充。

如果有人能给我一些建议,我将不胜感激,感谢

编辑-添加

    public BatteryRegionLog CurrentRegionLog
    {
        get { return _currentRegionLog; }
    }
    private BatteryRegionLog _currentRegionLog
    {
        get
        {
            if (this.BatteryRegionLogs.Count > 0)
            {
                BatteryRegionLog log = this.BatteryRegionLogs.OrderByDescending(item =>    item.LastModifiedDate).First();
                return log;
            }
            else
            {
                return null;
            }
        }
    }

执行不良的查询需要重写

您可以这样编写查询:

    if (comboBoxRegion.SelectedValue.ToString() != "0")
    {
        var id = int.Parse(comboBoxRegion.SelectedValue.ToString()
        Widgets = from b in Widgets
                  let currentRegionLog = 
                        b.BatteryRegionLogs
                         .OrderByDescending(item => item.LastModifiedDate)
                         .FirstOrDefault()
                  where currentRegionLog.RegionId == id)
                  select b;
    }
    ... // Same for the other criteria.
    dataGridViewWidget.DataSource = Widgets.ToList();

在执行ToList()之前,不会执行整个查询。由于所有内容都被转换为SQL,所以不需要空检查b.CurrentRegionLog != null。当不存在CurrentRegionLog时,SQL将对b.CurrentRegionLog.RegionId == id进行良好的评估。

编辑

由于CurrentRegionLogWidget类的计算属性,因此无法将其转换为SQL。我努力将计算属性的代码合并到查询中,只使用基本的导航属性,这样EF就可以再次将其转换为SQL。

尝试删除此行:

IEnumerable<Widget> results = Widgets.ToList();

只需使用顶部中的Widgets变量

.ToList()进入数据库并将所有数据实体化。

如果不调用.ToList(),则对于where子句的查询仍然是"打开的"