2013-08-20 3 views
1

Попытка конвертировать SQL-запрос в LINQ (так как я добавил код для загрузки двух таблиц SQL и сохранения их в DataSet в памяти). Поэтому мне нужно, чтобы LINQ выбирал тот же материал, что и SQL.Выберите несколько элементов в нескольких таблицах с помощью соединения

SQL Query

SELECT s.item1, s.item2, l.itemA, l.itemB 
FROM table1 s, table2 l 
WHERE l.itemA = name AND s.item1 = l.itemB 

То, что я до сих пор, что не компилируется (DBCONFIG является DataSet с несколькими таблицами)

var query = from l in DbConfig.Tables["table2"].AsEnumerable() 
      join s in DbConfig.Tables["table1"].AsEnumerable() on l.Field<string>("itemB") equals s.Field<string>("item1") 
      where l.Field<string>("itemA") == name 
      select s.item, s.item2, l.itemA, l.itemB; 

Я новичок в LINQ, так что любая помощь будет будь большой, спасибо!

+0

Что такое ошибка компилятора? –

ответ

3

Прежде всего, обратите внимание, что при вызове AsEnumerable запрос должен выполняться на клиенте, а не на сервере SQL. Я бы сильно рекомендую оставлять таблицы как IQueryable, чтобы этого избежать.

Далее, как Tim S. explains, так как ваши таблицы не сильно типизированы, используйте метод Field<T> для извлечения значения столбца.

Наконец, если вы хотите вернуть несколько столбцов, вам нужно сгруппировать результаты в анонимный тип:

var query = from l in DbConfig.Tables["table2"] 
      join s in DbConfig.Tables["table1"] 
      on l.Field<string>("itemB") equals s.Field<string>("item1") 
      where l.Field<string>("itemA") == name 
      select new { 
       item = s.Field<string>("item"), 
       item2 = s.Field<string>("item2"), 
       itemA = l.Field<string>("itemA"), 
       itemB = l.Field<string>("itemB") 
      }; 

Или создать именованный тип для представления результатов:

public class MyResultType { 
    public string item { get; set; } 
    public string item2 { get; set; } 
    public string itemA { get; set; } 
    public string itemB { get; set; } 
} 

var query = from l in DbConfig.Tables["table2"] 
      join s in DbConfig.Tables["table1"] 
      on l.Field<string>("itemB") equals s.Field<string>("item1") 
      where l.Field<string>("itemA") == name 
      select new MyResultType { 
       item = s.Field<string>("item"), 
       item2 = s.Field<string>("item2"), 
       itemA = l.Field<string>("itemA"), 
       itemB = l.Field<string>("itemB") 
      }; 
+0

Спасибо! Я попробовал это, и он говорит, что «DataRow не содержит определения для« itemx »и т. Д. Когда я пытаюсь выбрать этот способ: 'select new {servers.Field (« servername »), servers.Field (« ip »)};' он говорит: «Анонимный тип не может иметь несколько свойств с тем же именем». Есть предположения? – Hershizer33

+1

@ Hershizer33 В этом случае вам нужно будет указать имя: 'select new {servername = servers.Field (" servername "), ip = servers.Field (" ip ")};' - см. [* * Анонимные типы (Руководство по программированию на C#) **] (http://msdn.microsoft.com/en-us/library/vstudio/bb397696.aspx). –

+0

Кажется, будет работать ... последний вопрос, как я могу изменить 'query' в DataTable? Похоже, я могу сделать это, покупая создание DataTable, добавляя столбцы и вводя через «запрос», но я чувствую, что должен быть лучший способ ... – Hershizer33

2

Поскольку вы не имеете строго типизированных результатов, вы не можете выбирать результаты, например, s.item1; вы должны использовать Field<> (или что-то подобное), как и в остальной части вашего запроса. Кроме того, поскольку вы можете выбрать только один объект в запросе LINQ, и вы хотите четыре значения, вы должны либо выбрать их в новом анонимном типе, либо создать тип для их хранения.

var query = from l in DbConfig.Tables["table2"].AsEnumerable() 
      join s in DbConfig.Tables["table1"].AsEnumerable() 
       on l.Field<string>("itemB") equals s.Field<string>("item1") 
      where l.Field<string>("itemA") == name 
      select 
     new { Item1 = s.Field<string>("item1"), Item2 = s.Field<string>("item2"), 
      ItemA = l.Field<string>("itemA"), ItemB = l.Field<string>("itemB") }; 
1

Пожалуйста, попробуйте это

var data=from dr1 in DbConfig.Tables["table2"].AsEnumerable() 
     join dr2 in DbConfig.Tables["table1"].AsEnumerable() 
     on dr1.Field<string>("itemB") equals dr2.Field<string>("item1") 
     where dr1.Field<string>("itemA") == name 
     select new {item = dr2.Field<string>("item"), 
       item2 = dr2.Field<string>("item2"), 
       itemA = dr1.Field<string>("itemA"), 
       itemB = dr1.Field<string>("itemB") } 

Всегда использовать именованные типы (пользовательские классы) вместо анонимных типов для ремонтопригодности и расширяемости.

+0

@ p.s.w.g Да, вы правы. Мой запрос неверен, я пропустил другое условие соединения. Я обновлю свой ответ – kbvishnu

+0

Спасибо за исправление. –

0

Если вы хотели бы видеть лямбда синтаксис

var query = DbConfig.Tables["table1"].AsEnumerable() 
      .Join 
      (
       DbConfig.Tables["table2"].AsEnumerable(), 
       x=>x.Field<string>("item1"), 
       x=>x.Field<string>("itemB"), 
       (t1,t2)=>new {t1,t2} 
      ) 
      .Where 
      (
       x=>x.t2.Field<string>("itemA") == name 
      ) 
      .Select 
      (
       x=> 
       new 
       { 
        x.t1.Field<string>("item"), 
        x.t1.Field<string>("item2"), 
        x.t2.Field<string>("itemA"), 
        x.t2.Field<string>("itemB") 
       } 
      ) 
Смежные вопросы