Ошибка SQLiteException и SQLite рядом с "(": синтаксическая ошибка с Subsonic ActiveRecord

Я столкнулся с интересной ошибкой со следующим запросом LiNQ с использованием LiNQPad и при использовании Subsonic 3.0.x w/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);
        }

1 ответ

Решение

Избегайте ленивых вычислений, форсируя раннее выполнение с помощью.ToList() для одного из компонентов окончательного запроса. Результаты будут сохранены в памяти, поэтому постарайтесь убедиться, что вы выбираете небольшой набор данных, и не вводите неограниченный запрос или гигантский запрос в список.

Другие вопросы по тегам