Запрос LINQ в DataTable

Я пытаюсь выполнить запрос LINQ в объекте DataTable, и я прихожу к выводу, что выполнение таких запросов в DataTables непросто. Например:

var results = from myRow in myDataTable where results.Field("RowNo") == 1 select results; 

Это запрещено. Как я получу что-то вроде этого?

Я поражен тем, что запросы LINQ не разрешены в DataTables!

Вы не можете запросить коллекцию строк DataTable , поскольку DataRowCollection не реализует IEnumerable . Для DataTable необходимо использовать AsEnumerable() . Вот так:

 var results = from myRow in myDataTable.AsEnumerable() where myRow.Field("RowNo") == 1 select myRow; 

И как говорит Кейт, вам нужно добавить ссылку на System.Data.DataSetExtensions

AsEnumerable() возвращает IEnumerable . Если вам нужно преобразовать IEnumerable в DataTable , используйте расширение CopyToDataTable() .

 var results = from DataRow myRow in myDataTable.Rows where (int)myRow["RowNo"] == 1 select myRow 

Дело не в том, что в DataTables их намеренно не допускали, а именно, что DataTables предваряют IQueryable и общие конструкторы IEnumerable, по которым могут выполняться запросы Linq.

Оба интерфейса требуют некоторой проверки безопасности типа. Таблицы данных не строго типизированы. Это по той же причине, почему люди не могут запрашивать ArrayList, например.

Чтобы Linq работал, вам нужно сопоставить результаты с объектами, защищенными типом, и запросить их вместо этого.

Как @ ch00k сказал:

 using System.Data; //needed for the extension methods to work ... var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow; //select the thing you want, not the collection 

Вам также необходимо добавить ссылку на проект в System.Data.DataSetExtensions

 var query = from p in dt.AsEnumerable() where p.Field("code") == this.txtCat.Text select new { name = p.Field("name"), age= p.Field("age") }; 

Использование LINQ для управления данными в DataSet / DataTable

 var results = from myRow in tblCurrentStock.AsEnumerable() where myRow.Field("item_name").ToUpper().StartsWith(tbSearchItem.Text.ToUpper()) select myRow; DataView view = results.AsDataView(); 
 //Create DataTable DataTable dt= new DataTable(); dt.Columns.AddRange(New DataColumn[] { new DataColumn("ID",typeOf(System.Int32)), new DataColumn("Name",typeOf(System.String)) }); //Fill with data dt.Rows.Add(new Object[]{1,"Test1"}); dt.Rows.Add(new Object[]{2,"Test2"}); //Now Query DataTable with linq //To work with linq it should required our source implement IEnumerable interface. //But DataTable not Implement IEnumerable interface //So we call DataTable Extension method ie AsEnumerable() this will return EnumerableRowCollection // Now Query DataTable to find Row whoes ID=1 DataRow drow = dt.AsEnumerable().Where(p=>p.Field(0)==1).FirstOrDefault(); // 

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

 var results = from myRow in myDataTable.Rows.Cast() where myRow.Field("RowNo") == 1 select myRow; 

или

 var results = myDataTable.Rows.Cast() .FirstOrDefault(x => x.Field("RowNo") == 1); 

Вы можете использовать LINQ для объектов в коллекции Rows, например:

 var results = from myRow in myDataTable.Rows where myRow.Field("RowNo") == 1 select myRow; 

Попробуйте эту простую строку запроса:

 var result=myDataTable.AsEnumerable().Where(myRow => myRow.Field("RowNo") == 1); 

Попробуй это

 var row = (from result in dt.AsEnumerable().OrderBy( result => Guid.NewGuid()) select result).Take(3) ; 

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

 var results = myDataTable.Select("").FirstOrDefault(x => (int)x["RowNo"] == 1) 

Затем, если вы хотите получить конкретное значение:

 if(results != null) var foo = results["ColName"].ToString() 

Скорее всего, classы для DataSet, DataTable и DataRow уже определены в решении. Если это так, вам не понадобится ссылка DataSetExtensions.

Ex. Имя classа DataSet-> CustomSet, имя classа DataRow-> CustomTableRow (с определенными столбцами: RowNo, …)

 var result = from myRow in myDataTable.Rows.OfType() where myRow.RowNo == 1 select myRow; 

Или (как я предпочитаю)

 var result = myDataTable.Rows.OfType().Where(myRow => myRow.RowNo); 
 var results = from myRow in myDataTable where results.Field("RowNo") == 1 select results; 

В моем приложении я обнаружил, что использование LINQ to Datasets с расширением AsEnumerable () для DataTable, как было предложено в ответе, было очень медленным. Если вы хотите оптимизировать скорость, используйте библиотеку Json.Net Джеймса Ньютонкинга ( http://james.newtonking.com/json/help/index.html )

 // Serialize the DataTable to a json string string serializedTable = JsonConvert.SerializeObject(myDataTable); Jarray dataRows = Jarray.Parse(serializedTable); // Run the LINQ query List results = (from row in dataRows where (int) row["ans_key"] == 42 select row).ToList(); // If you need the results to be in a DataTable string jsonResults = JsonConvert.SerializeObject(results); DataTable resultsTable = JsonConvert.DeserializeObject(jsonResults); 
 IEnumerable result = from myRow in dataTableResult.AsEnumerable() select myRow["server"].ToString() ; 

Вы можете заставить его работать элегантно через linq следующим образом:

 from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable() where prod.Field("UnitPrice") > 62.500M select prod 

Или как динамический linq это (AsDynamic вызывается непосредственно на DataSet):

 TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M) 

Я предпочитаю последний подход, пока он является наиболее гибким. PS: Не забудьте подключить System.Data.DataSetExtensions.dll ссылку

Для VB.NET Код будет выглядеть так:

 Dim results = From myRow In myDataTable Where myRow.Field(Of Int32)("RowNo") = 1 Select myRow 

Пример того, как это сделать, приведен ниже:

 DataSet dataSet = new DataSet(); //Create a dataset dataSet = _DataEntryDataLayer.ReadResults(); //Call to the dataLayer to return the data //LINQ query on a DataTable var dataList = dataSet.Tables["DataTable"] .AsEnumerable() .Select(i => new { ID = i["ID"], Name = i["Name"] }).ToList(); 

Попробуй это…

 SqlCommand cmd = new SqlCommand( "Select * from Employee",con); SqlDataReader dr = cmd.ExecuteReader( ); DataTable dt = new DataTable( "Employee" ); dt.Load( dr ); var Data = dt.AsEnumerable( ); var names = from emp in Data select emp.Field( dt.Columns[1] ); foreach( var name in names ) { Console.WriteLine( name ); } 

вы можете попробовать это, но вы должны быть уверены, что тип значений для каждого столбца

 List result = myDataTable.AsEnumerable().Select(x=> new MyClass(){ Property1 = (string)x.Field("ColumnName1"), Property1 = (int)x.Field("ColumnName2"), Property1 = (bool)x.Field("ColumnName3"), }); 
  • Linq Query Group и выбор первых элементов
  • Сумма предметов в коллекции
  • LINQ Distinct () для определенного свойства
  • Буквенно-цифровая сортировка с использованием LINQ
  • Как проверить, является ли IEnumerable пустой или пустой?
  • Ловушка внешней переменной
  • LINQ не обновляется .SubmitChanges ()
  • Невозможно создать постоянное значение - только примитивные типы
  • Выполнение поиска () по сравнению с FirstOrDefault ()
  • Использование IQueryable с Linq
  • Как «застегнуть» или «повернуть» переменное количество списков?
  • Давайте будем гением компьютера.