Я пытаюсь выполнить запрос LINQ к объекту DataTable, и странным образом обнаруживаю, что выполнение таких запросов к объектам DataTable не является простым. Например:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
Это не разрешено Как я могу получить что-то вроде этого работает?
Я поражен, что запросы LINQ не разрешены в DataTables!
Ответы:
Вы не можете запрос против
DataTable
«ы Rows коллекции, так какDataRowCollection
не выполняетIEnumerable<T>
. Вам нужно использоватьAsEnumerable()
расширение дляDataTable
. Вот так:И, как говорит @Keith , вам нужно добавить ссылку на System.Data.DataSetExtensions
AsEnumerable()
возвращаетсяIEnumerable<DataRow>
. Если вам нужно конвертироватьIEnumerable<DataRow>
в aDataTable
, используйтеCopyToDataTable()
расширение.Ниже приведен запрос с лямбда-выражением,
источник
using System.Data;
myDataTable.Rows
вместо этого, как предложил @JoelFan.myDataTable.Rows
заключается в том, чтоmyRow
переменная явно приведена кDataRow
. Когда он компилируется, этот запрос переписывается вmyDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)
. Лично я не считаю вызовAsEnumerable()
более сложным, чем вызовCast<DataRow>()
. Насколько я знаю, производительность одинакова, так что это просто вопрос предпочтений.источник
(int)myRow["RowNo"]
на общую формуmyRow.Field<int>("RowNo")
для более удобной поддержки типов, допускающих обнуление.Дело не в том, что они были намеренно запрещены в DataTables, просто DataTable предшествуют IQueryable и универсальным конструкциям IEnumerable, для которых могут выполняться запросы Linq.
Оба интерфейса требуют некоторой проверки безопасности типа. DataTables не являются строго типизированными. Это та же самая причина, по которой люди, например, не могут запрашивать ArrayList.
Чтобы Linq работал, вам нужно сопоставить результаты с типобезопасными объектами и вместо этого выполнить запрос.
источник
Как сказал @ ch00k:
Вам также необходимо добавить ссылку на проект в
System.Data.DataSetExtensions
источник
myRow
или использованииCast<DataRow>()
наRows
. Лучше использоватьAsEnumerable()
.System.Linq
аSystem.Data.DataSetExtensions
затемmyDataTable.Rows
возвращает перечислимую коллекцию вDataRow
любом случае. Это могло измениться, прошло уже десять лет с тех пор, как я его использовал.DataSet
расширения не попали в .NET Core или .NET Standard, они уже устарели, когда я опубликовал этот ответ. Я действительно не буду использоватьDataSet
в новых проектах, есть гораздо лучшие модели доступа к данным, как для простоты кодирования и производительности.DataRowCollection
не реализуютсяIEnumerable<T>
простоIEnumerable
и поэтому не работают со строго типизированным LINQ.поля name и age теперь являются частью объекта запроса и доступны следующим образом: Console.WriteLine (query.name);
источник
MessageBox.Show(name)
не определено.Я понимаю, что на это уже отвечали несколько раз, но просто чтобы предложить другой подход:
Мне нравится использовать этот
.Cast<T>()
метод, он помогает мне сохранять здравый смысл в том, чтобы видеть явный тип, заданный и в глубине, я думаю, в.AsEnumerable()
любом случае вызывает его:или
Как отмечено в комментариях, никакие другие сборки не нужны, так как это часть Linq ( ссылка )
источник
Использование LINQ для манипулирования данными в DataSet / DataTable
источник
System.Data.DataSetExtensions
.источник
Попробуйте эту простую строку запроса:
источник
Вы можете использовать LINQ для объектов в коллекции Rows, например так:
источник
DataTable.Rows
что не реализуетIEnumerable
, я не вижу, как этот запрос может скомпилироваться.Это простой способ, который работает для меня и использует лямбда-выражения:
Тогда, если вы хотите конкретное значение:
источник
Попробуй это
источник
Скорее всего, классы для DataSet, DataTable и DataRow уже определены в решении. Если это так, вам не понадобится ссылка DataSetExtensions.
Ex. Имя класса DataSet-> CustomSet, имя класса DataRow-> CustomTableRow (с определенными столбцами: RowNo, ...)
Или (как я предпочитаю)
источник
источник
В моем приложении я обнаружил, что использование LINQ to Datasets с расширением AsEnumerable () для DataTable, как было предложено в ответе, было чрезвычайно медленным. Если вы заинтересованы в оптимизации скорости, используйте библиотеку Джеймса Ньютонкинга Json.Net ( http://james.newtonking.com/json/help/index.html ).
источник
System.Data.DataRow
объектов. Таблица сериализованных и проанализированных данных создает облегченные данные, состоящие только из имен столбцов и значений каждой строки. Когда запрос выполняется, он загружает данные в память, что для большого набора данных может включать обмен. Иногда накладные расходы на несколько операций меньше, чем накладные расходы на копирование больших объемов данных в память и из нее.Для VB.NET код будет выглядеть так:
источник
источник
Пример того, как этого добиться, приведен ниже:
источник
Попробуй это...
источник
Вы можете заставить его работать элегантно через linq следующим образом:
Или как динамический linq this (AsDynamic вызывается непосредственно в DataSet):
Я предпочитаю последний подход, пока он самый гибкий. PS: не забудьте подключить
System.Data.DataSetExtensions.dll
ссылкуисточник
Вы можете попробовать это, но вы должны быть уверены, что тип значений для каждого столбца
источник
Я предлагаю следующее решение:
Глядя на документацию DataView , первое, что мы можем увидеть, это:
Из этого я получаю то, что DataTable предназначен только для хранения данных, а DataView позволяет нам «запрашивать» данные из DataTable.
Вот как это работает в данном конкретном случае:
Вы пытаетесь реализовать оператор SQL
в «DataTable язык». В C # мы читаем это так:
который выглядит в C # так:
источник
источник