0

我在使用 LiNQPad 和在我的项目中使用 Subsonic 3.0.xw/ActiveRecord 的以下 LiNQ 查询中遇到了一个有趣的错误,我想与遇到它的其他人分享错误和解决方案。

下面的 linq 语句旨在将 tblSystemsValues 集合中的条目分组到相应的系统中,然后提取具有最高 ID 的系统。

from ksf in KeySafetyFunction where ksf.Unit == 2 && ksf.Condition_ID == 1 
   join sys in tblSystems on ksf.ID equals sys.KeySafetyFunction
   join xval in (from t in tblSystemsValues 
group t by t.tblSystems_ID into groupedT 
  select new 
  { 
    sysId = groupedT.Key, 
    MaxID = groupedT.Max(g=>g.ID), 
    MaxText = groupedT.First(gt2 => gt2.ID ==  
                groupedT.Max(g=>g.ID)).TextValue,
    MaxChecked = groupedT.First(gt2 => gt2.ID ==  
                groupedT.Max(g=>g.ID)).Checked
   }) on sys.ID equals xval.sysId
select new {KSFDesc=ksf.Description, sys.Description, xval.MaxText, xval.MaxChecked}

就其本身而言,用于分组到 groupedT 的子查询可以完美地工作,并且将 KeySafetyFunctions 与其在 tblSystems 中的系统匹配的查询也可以完美地独立工作。

但是,当尝试在 linqpad 或我的项目中运行已完成的查询时,我一直遇到SQLiteException SQLite Error Near "("

首先,我尝试在我的项目中拆分查询,因为我知道我可以在必要时对结果运行一个 foreach 循环。但是,我继续收到同样的异常!

我最终将查询分成三个独立的部分,然后我才意识到是查询的延迟执行让我很生气。然后很明显,在下面的 myProtectedSystem 查询之后添加.ToList()说明符是在组合和优化查询之后避免延迟执行的关键,并且尽管我遇到了 SQLite 驱动程序的问题,但能够获得我的结果。

// determine the max Text/Checked values for each system in tblSystemsValue
var myProtectedValue = from t in tblSystemsValue.All()
        group t by t.tblSystems_ID into groupedT
           select new {
             sysId = groupedT.Key,
             MaxID = groupedT.Max(g => g.ID),
             MaxText = groupedT.First(gt2 => gt2.ID ==groupedT.Max(g => g.ID)).TextValue,
             MaxChecked = groupedT.First(gt2 => gt2.ID ==groupedT.Max(g => g.ID)).Checked};
// get the system description information and filter by Unit/Condition ID
var myProtectedSystem = (from ksf in KeySafetyFunction.All()
        where ksf.Unit == 2 && ksf.Condition_ID == 1
          join sys in tblSystem.All() on ksf.ID equals sys.KeySafetyFunction
             select new {KSFDesc = ksf.Description, sys.Description, sys.ID}).ToList();
// finally join everything together AFTER forcing execution with .ToList()
 var joined = from protectedSys in myProtectedSystem
         join protectedVal in myProtectedValue on protectedSys.ID equals protectedVal.sysId
           select new {protectedSys.KSFDesc, protectedSys.Description, protectedVal.MaxChecked, protectedVal.MaxText};
  // print the gratifying debug results
  foreach(var protectedItem in joined)
        {
            System.Diagnostics.Debug.WriteLine(protectedItem.Description + ", " + protectedItem.KSFDesc + ", " + protectedItem.MaxText + ", " + protectedItem.MaxChecked);
        }
4

1 回答 1

0

通过在最终查询的组件之一上强制使用 .ToList() 提前执行来避免延迟评估。结果将进入内存,因此请尽量确保您选择的是一小部分数据,并且不要将无界查询或巨大查询强制放入列表中。

于 2010-04-05T01:27:04.387 回答