2010-01-02 1 views
3

Как написать такие же запросы в EF?Подпроцесс Entity Framework

select * from table1 where col1 in (select col1 from table2 where col2 = 'xyz') 

или

select * from table1 where col1 not in (select col1 from table2 where col2 = 'xyz') 

Я пытался что-то вроде этих

from t1 in table1 
where (from t2 in table2 where col2 = 'xyz' select t2.col1).Contains(t1.col1) 
select t1 

и

from t1 in table1 
where !(from t2 in table2 where col2 = 'xyz' select t2.col1).Contains(t1.col1) 
select t1 

эти вопросы работают отлично LINQPad или Linq к Sql

+0

Если существующие ответы не являются тем, что вы ищете, напишите * что произошло *, когда вы пытались использовать те выражения запроса, которые вы опубликовали. Вы получили ошибку времени компиляции? Ошибка выполнения? Какая ошибка? Или вы просто не получили ожидаемых результатов? – Aaronaught

+0

Прежде всего, за немедленный ответ! это то, что я пытаюсь выполнить - выберите * от table1 где somestringmanipulation (col1) в (выберите somestringmanipulation (col1) из table2 где Col2 = 'хуг') где table1 и table2 не имеет отношения , Я получаю следующую ошибку, когда пытаюсь использовать Содержит, но дает результаты в LinqPad LINQ to Entities не распознает метод 'Boolean Содержит [Int32] (System.Linq.IQueryable'1 [System. Int32], Int32), и этот метод не может быть переведен в выражение хранилища. – Gokulnath

+0

Я не думаю, что смогу выполнить это, не используя IN или NOT IN, на время я планировал использовать хранимую процедуру, а позже я рассмотрю http://stackoverflow.com/questions/374267/contains -workaround-using-linq-to-entities – Gokulnath

ответ

0

Если есть внешний ключ на месте, вы должны просто использовать свойство ассоциации и пусть EF перевести его в правильном подключении/подзапросов, как:

from t1 in table1 
where t1.Table2.col2 == "xyz" 
select t1 

Не уверен, что о вашем конкретном случае, но одна ключевой разница заключается в том, что EF по умолчанию не делает ленивой загрузки, поэтому вам может понадобиться столбцы Include() (не нужно было бы это в linq-to-sql или LinqPad, который использует linq-to-sql), чтобы загрузить их или, наоборот, Затем загрузите().

http://msdn.microsoft.com/en-us/library/bb896249.aspx

Если вы могли бы в конечном итоге обмена немного более конкретную схему, мы могли бы сказать наверняка, если это то, что происходит, я надеюсь.

+2

Lazy-loading не должно быть проблемой здесь, потому что это преобразование запроса - это никогда не оценивает 't1.Table2.col2' в CLR. Если есть разница между Linq to SQL (который использует LinqPad), то я подозреваю, что это потому, что EF не знает, как преобразовать выражение так, как оно написано, но, конечно, нам нужно было знать, что на самом деле произошло, когда он попытался запросов, чтобы быть уверенным. – Aaronaught

+0

Аарон прав: ленивая загрузка (или нет) * не будет * фактором здесь. –

6

Этот тип подзапроса может быть уплощен в соединение, которое, как я выбрал бы написать его здесь:

SQL Версия:

SELECT t1.col1, t1.col2, t1.col3, ... 
FROM table1 t1 
INNER JOIN table2 t2 
    ON t1.col1 = t2.col1 
WHERE t2.col2 = 'xyz' 

Linq Версия:

var query = 
    from t1 in context.Table1 
    where t1.AssociationToTable2.Col2 == "xyz" 
    select new { t1.Col1, t1.Col2, ... }; 

Где AssociationToTable2 - свойство отношений - оно автоматически соединяется. Или, если вы не имеете отношения:

var query = 
    from t1 in context.Table1 
    join t2 in context.Table2 
     on t1.Col1 equals t2.Col1 
    where t2.Col2 == "xyz" 
    select new { t1.Col1, t1.Col2, ... }; 

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

Если вы абсолютно должны сделать это «IN» способ, я предлагаю перечислить ответы в this question.