2016-02-10 4 views
0

У меня есть два классагде состояние внутри вложенного списка LINQ

public class Item 
    { 
    public string LineID{ get; set; } 
    public string ItemNo{ get; set; } 
    public List<Itemcode> ItemcodeList{ get; set; } 
    } 

    public class Itemcode 
    { 
     public string LineID{ get; set; } 
     public string code { get; set; } 
     public string codeValue { get; set; } 
    } 

и два DataTables ds.Tables [1] и ds.Tables [2]

Я преобразование данных из двух набора данных в список класса Item, который также содержит список класса Артикул

То, что я делаю, так

List<Item> items = ds.Tables[1].AsEnumerable().Select(dataRow => new Item 
        { 
         LineID= Convert.ToString(dataRow.Field<int>("LineID")), 
         ItemNo= dataRow.Field<string>("ItemNo"), 
         ItemcodeList = ds.Tables[2].AsEnumerable().Select(row => new Itemcode 
         { 
          code= Convert.ToString(row.Field<string>("code")), 
          codeValue = Convert.ToString(row.Field<string>("codeValue")), 
         }).ToList() 
        }).ToList(); 

Вышеприведенный код дает все таблицы ds.Tables [2] по каждой строке ds.Table [1]

Но я хочу только те строки, где LineID ds.Table [1] соответствует LineID ds.Table [2], где я должен изменить условию

+0

зачем вам нужен AsEnumerable()? – enkryptor

+0

becasue DataTable не реализует IEnumerable – Viru

ответ

0

Просто добавьте где положение и сравнить его с LineId из DataRow

List<Item> items = ds.Tables[1].AsEnumerable().Select(dataRow => new Item 
        { 
         LineID= Convert.ToString(dataRow.Field<int>("LineID")), 
         ItemNo= dataRow.Field<string>("ItemNo"), 
         ItemcodeList = ds.Tables[2].AsEnumerable().Where(ic=>ic.Field<int>("LineId")==dataRow.Field<int>("LineID")).Select(row => new Itemcode 
         { 
          code= Convert.ToString(row.Field<string>("code")), 
          codeValue = Convert.ToString(row.Field<string>("codeValue")), 
         }).ToList() 
        }).ToList(); 

Дополнительная информация

Здесь AsEnumerable отличается от AsQueryable .... Вот данные уже извлекается из базы данных и заполняется в DataTable вашего объекта DataSet .... Причина вы должны сделать AsEnumerable потому, что DataTable не реализует IEnumerable < T> и все ваши запросы Linq работать только от типа IEnumerable < T>.

+0

ds.Tables [2] .AsEnumerable(). Where() - это будет извлекать ВСЕ записи и применять condidion after – enkryptor

+2

, у вас уже есть записи в памяти ... он будет перечислять и выберите только те, которые удовлетворяют условию – Viru

+0

@Viru Я получаю ошибку System.Data.DataRow 'не содержит определения для' LineId 'и никакого метода расширения' LineId ', принимающего первый аргумент типа' System.Data.DataRow 'at Where (ic => ic.LineId == dataRow.Field

3

ИМХО, чистое решение (которое также повышает производительность для больших наборов данных) является первым создать поиск из детей, а затем собрать родитель:

 var itemCodes = (
      from dataRow in ds.Tables[2].AsEnumerable() 
      select new Itemcode 
      { 
       LineID = dataRow.Field<string>("LineID"), 
       code = dataRow.Field<string>("code"), 
       codeValue = dataRow.Field<string>("code") 
      }).ToLookup(ic => ic.LineID); 

     var lines = (
      from dataRow in ds.Tables[1].AsEnumerable() 
      let lineID = dataRow.Field<string>("LineID") 
      select new Item 
      { 
       LineID = lineID, 
       ItemNo = dataRow.Field<string>("ItemNo"), 
       ItemcodeList = itemCodes[lineID].ToList() 
      }).ToList(); 

Или, если вы предпочитаете синтаксис цепи метода:

 var itemCodes = ds.Tables[2].AsEnumerable().Select(dataRow => new Itemcode 
     { 
      LineID = dataRow.Field<string>("LineID"), 
      code = dataRow.Field<string>("code"), 
      codeValue = dataRow.Field<string>("code") 
     }).ToLookup(ic => ic.LineID); 

     var lines = ds.Tables[1].AsEnumerable() 
      .Select(dataRow => new {dataRow, lineID = dataRow.Field<string>("LineID")}) 
      .Select(item => new Item 
      { 
       LineID = item.lineID, 
       ItemNo = item.dataRow.Field<string>("ItemNo"), 
       ItemcodeList = itemCodes[item.lineID].ToList() 
      }).ToList(); 
+2

@Silvermind, какая у вас точка? – Magnus

+1

@Silvermind данные уже в памяти. И поиск будет поддерживать только ref а не к их объектам. – Magnus

3

Я думаю, что использование group join было бы хорошим решением здесь.

var items= (from tbl1 in ds.Tables[1].AsEnumerable() 
      join tbl2 in ds.Tables[2].AsEnumerable() 
       on tbl1.Field<int>("LineId") equals tbl2.Field<int>("LineID") into g 
      select new Item 
      { 
       LineID = tbl1.Field<int>("LineID").ToString(), 
       ItemNo = tbl1.Field<string>("ItemNo"), 
       ItemcodeList = g.Select(row => 
        new Itemcode 
        { 
        code = row.Field<string>("code").ToString(), 
        codeValue = row.Field<string>("codeValue").ToString(), 
        }).ToList() 
      }).ToList(); 
+0

Это действительно лучшее решение! –

+0

Да, это самое ясное решение. Просто для удовольствия, посмотрите на http: // sourcesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,1bdae7e7505451ef. На самом деле сначала создается поиск :-). – jeroenh

0

Если вы хотите лямбды решения, должны работать:

List<Item> items = 
      ds.Tables[0].AsEnumerable().GroupJoin(
      ds.Tables[1].AsEnumerable(), 
      tab1 => tab1.Field<int>("LineID"), 
      tab2 => tab2.Field<int>("LineID"), 
      (tab1, tab2) => new Item 
         { 
          LineID = Convert.ToString(tab1.Field<int>("LineID")), 
          ItemNo = tab1.Field<string>("ItemNo"), 
          ItemcodeList = tab2.AsEnumerable().SelectMany(codes=> 
           new List<Itemcode>         
           { 
            new Itemcode { code = codes.Field<string>("Code")} 
           } 
          ).ToList() 
         } 
      ).ToList(); 
Смежные вопросы