Я столкнулся с интересной ошибкой в следующем запросе LiNQ с использованием LiNQPad и при использовании Subsonic 3.0.x с ActiveRecord в моем проекте и хотел поделиться этой ошибкой и разрешением для всех, кто столкнулся с ней.
Оператор 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 для результатов. Однако я продолжал получать то же исключение!
В конце концов я разделил запрос на три отдельные части, прежде чем понял, что меня убивает ленивое выполнение запросов. Затем стало ясно, что добавление спецификатора .ToList () после запроса myProtectedSystem, приведенного ниже, является ключом к тому, чтобы избежать ленивого выполнения после объединения и оптимизации запроса и возможности получить мои результаты, несмотря на проблемы, с которыми я столкнулся драйвер 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);
}