Estou tentando executar uma consulta LINQ em um objeto DataTable e, estranhamente, estou descobrindo que executar essas consultas no DataTables não é simples. Por exemplo:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
Isso não é permitido. Como obtenho algo assim funcionando?
Estou surpreso que as consultas LINQ não sejam permitidas no DataTables!
Respostas:
Você não pode consultar contra o
DataTable
's linhas coleção, desdeDataRowCollection
não implementaIEnumerable<T>
. Você precisa usar aAsEnumerable()
extensão paraDataTable
. Igual a:E como @Keith diz, você precisará adicionar uma referência ao System.Data.DataSetExtensions
AsEnumerable()
retornaIEnumerable<DataRow>
. Se você precisar converterIEnumerable<DataRow>
para aDataTable
, use aCopyToDataTable()
extensãoAbaixo está uma consulta com a expressão Lambda,
fonte
using System.Data;
myDataTable.Rows
como o @JoelFan sugeriu.myDataTable.Rows
é porque amyRow
variável é convertida explicitamenteDataRow
. Quando é compilada, essa consulta é reescrita paramyDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)
. Pessoalmente, não acho a ligaçãoAsEnumerable()
mais complicada do que a ligação paraCast<DataRow>()
. Até onde eu sei, o desempenho é o mesmo, então é apenas uma questão de preferência.fonte
(int)myRow["RowNo"]
pelo formulário genéricomyRow.Field<int>("RowNo")
para oferecer suporte mais conveniente a tipos anuláveis.Não é que eles não tenham sido deliberadamente permitidos no DataTables, apenas o DataTables é anterior às construções IQueryable e IEnumerable genéricas nas quais as consultas do Linq podem ser executadas.
Ambas as interfaces requerem alguma validação de segurança de tipo de classificação. DataTables não são fortemente tipadas. Esse é o mesmo motivo pelo qual as pessoas não podem consultar um ArrayList, por exemplo.
Para que o Linq funcione, você precisa mapear seus resultados em relação a objetos com segurança de tipo e, em vez disso, consultar esses itens.
fonte
Como @ ch00k disse:
Você também precisa adicionar uma referência de projeto ao
System.Data.DataSetExtensions
fonte
myRow
ou utilizaçãoCast<DataRow>()
emRows
. Melhor usarAsEnumerable()
.System.Linq
eSystem.Data.DataSetExtensions
, em seguida,myDataTable.Rows
retorna uma coleção enumerável deDataRow
qualquer maneira. Isso pode ter mudado, faz uma década desde que eu o usei.DataSet
extensões não entrem no .NET Core ou .NET Standard, elas já estavam desatualizadas quando publiquei esta resposta. Eu realmente não usariaDataSet
em novos projetos, existem modelos de acesso a dados muito melhores, tanto para facilitar a codificação quanto para o desempenho.DataRowCollection
não implementamIEnumerable<T>
apenasIEnumerable
e, portanto, não funcionam com LINQ fortemente tipado.os campos nome e idade agora fazem parte do objeto de consulta e podem ser acessados da seguinte maneira: Console.WriteLine (query.name);
fonte
MessageBox.Show(name)
é indefinido.Sei que isso foi respondido algumas vezes, mas apenas para oferecer outra abordagem:
Eu gosto de usar o
.Cast<T>()
método, ele me ajuda a manter a sanidade ao ver o tipo explícito definido e, no fundo, acho que.AsEnumerable()
chama assim mesmo:ou
Conforme observado nos comentários, nenhum outro conjunto é necessário, pois faz parte do Linq ( Referência )
fonte
Usando o LINQ para manipular dados no DataSet / DataTable
fonte
System.Data.DataSetExtensions
.fonte
Tente esta linha de consulta simples:
fonte
Você pode usar o LINQ para objetos na coleção Rows, da seguinte maneira:
fonte
DataTable.Rows
não é implementadoIEnumerable
, não consigo ver como essa consulta pode ser compilada.Esta é uma maneira simples que funciona para mim e usa expressões lambda:
Então, se você deseja um valor específico:
fonte
Tente isto
fonte
Provavelmente, as classes para o DataSet, DataTable e DataRow já estão definidas na solução. Se for esse o caso, você não precisará da referência DataSetExtensions.
Ex. Nome da classe DataSet-> CustomSet, Nome da classe DataRow-> CustomTableRow (com colunas definidas: RowNo, ...)
Ou (como eu prefiro)
fonte
fonte
No meu aplicativo, descobri que o uso de LINQ to Datasets com a extensão AsEnumerable () para DataTable, conforme sugerido na resposta, era extremamente lento. Se você estiver interessado em otimizar a velocidade, use a biblioteca Json.Net de James Newtonking ( http://james.newtonking.com/json/help/index.html )
fonte
System.Data.DataRow
objetos pesados . A tabela de dados serializados e analisados cria dados leves que consistem apenas nos nomes e valores das colunas de cada linha. Quando a consulta é executada, ela carrega os dados na memória, o que para um grande conjunto de dados pode envolver a troca. Às vezes, a sobrecarga de várias operações é menor que a sobrecarga de copiar grandes quantidades de dados dentro e fora da memória.Para VB.NET O código será semelhante a este:
fonte
fonte
Exemplo de como conseguir isso fornecido abaixo:
fonte
Tente isso ...
fonte
Você pode fazê-lo funcionar de maneira elegante via linq assim:
Ou como o linq dinâmico, este (o AsDynamic é chamado diretamente no DataSet):
Prefiro a última abordagem, enquanto is é a mais flexível. PS: Não esqueça de conectar
System.Data.DataSetExtensions.dll
referênciafonte
você pode tentar isso, mas deve ter certeza de que o tipo de valores para cada coluna
fonte
Proponho a seguinte solução:
Observando a documentação do DataView , a primeira coisa que podemos ver é:
O que estou obtendo disso é que o DataTable se destina apenas a armazenar dados e o DataView nos permite "consultar" o DataTable.
Aqui está como isso funciona neste caso específico:
Você tenta implementar a instrução SQL
no "idioma DataTable". Em C #, lemos assim:
que fica em c # assim:
fonte
fonte