Свойства выражения Linq to SQL, которые можно перевести на SQL - PullRequest
3 голосов
/ 12 декабря 2011

У меня есть класс LINQ to SQL, мы назовем его Test, и я хочу иметь возможность доступа к свойствам с помощью запросов LINQ, но я получаю известную ошибку времени выполнения «Нет поддерживаемого перевода в SQL».Я заинтересован в концептуальной проблеме.Вот мой упрощенный класс:

public class Test
{ 
  public int ID {get; set;} // Stored in Database
  public int NonForeignKeyValue {get; set;} // Stored in Database
}

Вот пример того, чего я пытаюсь достичь, но я не хочу, чтобы накладные расходы всегда явно записывали объединение в LINQ:

var db = (new DataContext()).GetTable<Test>();
var q = (from t in db.GetTable<Test>()
         join o in db.GetTable<OtherTable>() on o.ID equals t.ID
         where t.OtherStuff
         select t)

Я хотел бы иметь возможность добавить свойство к Test, которое сообщает мне, есть ли в OtherTable какие-либо строки, которые можно объединить с Test:

  public bool IsInOtherTable
  {
    get
    {
       return (new DataContext())
              .GetTable<OtherTabke>()
              .Any(x => x.NonForeignKeyValue == this.NonForeignKeyValue));
    }
  }

В конечном итоге это то, что я хочу, чтобы мой код выглядел, но это ошибки.Я в основном хочу вернуть все записи, которые содержат некоторое вычисленное значение базы данных:

using (DataContext db =  new DataContext())
{
   var q = db.GetTable<Test>()
             .Where(x => x.IsInOtherTable && x.OtherStuff); //Error
}       

Я в основном пытаюсь уберечь себя от написания этого кода каждый раз, когда я хочу проверить, есть ли в Test определенная информация в другой таблице,Меня не очень интересует конкретная проблема, которую я описал, меня больше интересует, как концептуально добавить часть соединения в SQL и все еще использовать LINQ.Я предполагаю, что использую Linq.Expression, но я действительно не знаю, и я не знаю, как это сделать.

Кроме того, я мог бы просто написать реальный SQL, поскольку он не так уж сложен, но я хотел бы знать, как обойти это и при этом использовать LINQ.

Редактировать: я пробовал это свойство, но я получаю ту же ошибку.Это сложнее, чем просто изменить тип возвращаемого значения на выражение ...

public System.Linq.Expressions.Expression<Func<Article3, bool>> Exists
{
    get
    {
       using (DataContext db =  new DataContext())
       {
         return i => db.GetTable<OtherTable>()
                       .Any(x => x.NonForeignKeyValue == i.NonForeignKeyValue));
       }
    }
}        

Ответы [ 2 ]

1 голос
/ 12 декабря 2011

Каждый раз, когда генератор linq должен преобразовать код в запрос, он должен обрабатывать дерево выражений.

В ваших примерах вы не передаете выражение, а скорее - свойства, делегаты, то есть вещи, в которые посетитель выражения не может "войти".

В общем, попробуйте переосмыслить ваши условия, чтобы вместо bool у вас было Expression<T, bool> и т. Д.

http://netpl.blogspot.com/2008/02/linq-to-object-vs-linq-to-sql-and.html

0 голосов
/ 12 декабря 2011

Во-первых, я думаю, что вы, возможно, переоцениваете «издержки, связанные с написанием объединения в явном виде в LINQ».Это дополнительная строка кода, которая имеет преимущество относительно самодокументирования того, что вы делаете (всегда приятно), и любой другой подход будет сначала превращен в SQL, а затем в план запроса, который будетбыть по крайней мере столь же дорогим для выполнения, возможно, более дорогим (SQLServer - это хорошее объединение!)

Тем не менее, есть две альтернативы, о которых я могу подумать. свойство класса, которое определяет эту связь с другой таблицей.Затем вы можете проверить, является ли оно пустым в вашем запросе (или EntitySet, если оно находится на другой стороне отношения один ко многим).

Другой способ - определить функцию SQL, которая возвращает bit результат, указывающий, относится ли идентификатор к строке, которая относится или не относится к другой таблице.

Затем определите защищенный метод в классе, производном от DataContext, который соответствует сигнатуре в терминах C #, и имеет Атрибут функции , сопоставляющий его с этой функцией SQL.(Поскольку это не то, что вы можете дать разумную версию без использования db в версии C #, вы можете реализовать функцию C #, вызвав ExecuteMethodCall ).

Тогда выможно использовать этот метод вместо объединения.

Тем не менее, это, вероятно, менее очевидно в коде и рискует быть менее эффективным, чем просто сохранение объединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...