我在使用 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);
}