Neste Post, vou demonstrar como podemos gerar um DataTable a partir de uma query realizada com o LINQ utilizando ADO Data Entity.
Em determinadas situações como uma migração de sistema, por exemplo, necessitamos adaptar nosso código para trabalhar da maneira mais transparente possível e causando um menor impacto na aplicação. Vou dar um exemplo. Imagine uma aplicação onde a camada de dados faz um acesso a base e monta um DataTable devolvendo para a aplicação consumir. Nesta aplicação temos a necessidade de fazer uma migração para ADO.NET Entity Framework. Seria um impacto muito grande se, a princípio, tentássemos migrar a camada de dados e a aplicação junto para que, ao invés de DataTable, a aplicação passe a receber objetos do Entity Framework. Para isso, desenvolví uma pequena rotina para gerar DataTable a partir de uma query LINQ no Entity Framework.
A primeira parte é a query com o LINQ:
AdventureWorksEntities db = new AdventureWorksEntities();
IQueryable _query = (from c in db.Address
where c.City.Equals("Bothell", StringComparison.CurrentCultureIgnoreCase)
select new
{
ID = c.AddressID,
Endereco = c.AddressLine1,
Cidade = c.City,
CaixaPostal = c.PostalCode
}
).OrderBy(o=>o.Endereco);
Reparem que no Retorno eu recebo um objeto do tipo IQueryable. Ele é uma interface que guarda os dados da query como: provider, expressão e os tipos de elemento que são retornados quando a expressão é executada. Como o retorno da query por definição implementa IQueryable, esta atividade fica transparente. O IQueryable também implementa IEnumerable, o que possibilita também percorrer a lista retornada pela query.
Eis o Método que transforma o objeto IQueriable em DataTable:
public static DataTable RetornarDataTable(IQueryable pObjQuery)
{
DataTable _dt = new DataTable();
//Cria o DataTable
foreach (var item in pObjQuery)
{
Type t = item.GetType();
PropertyInfo[] properties = t.GetProperties();
for (int i = 0; i < properties.Length; i++)
{
_dt.Columns.Add(properties[i].Name);
}
break;
}
IEnumerator en = (IEnumerator)pObjQuery.GetEnumerator();
//Popula o DataTable
while (en.MoveNext())
{
Type ten = en.Current.GetType();
PropertyInfo[] propertiesen = ten.GetProperties();
DataRow _dtrow = _dt.NewRow();
for (int i = 0; i < propertiesen.Length; i++)
{
object obj = propertiesen[i].GetValue(en.Current, new object[] { });
_dtrow[i] = obj;
}
_dt.Rows.Add(_dtrow);
}
return _dt;
}
Reparem que neste código, procurei separar a montagem do DataTable, inclusive com os nomes das colunas fiéis a query, e logo após percorro a lista carregando os registros.
Abaixo o Código Completo para Testes:
static void Main(string[] args)
{
DataTable _dtEnderecos = RetornarEnderecos();
foreach (DataColumn col in _dtEnderecos.Columns)
{
Console.WriteLine(col.ColumnName);
}
Console.WriteLine("");
foreach (DataRow dados in _dtEnderecos.Rows)
{
Console.WriteLine(dados["ID"] + " " + dados["Endereco"] + " " + dados["Cidade"] + " " + dados["CaixaPostal"]);
}
Console.Read();
}
public static DataTable RetornarEnderecos()
{
AdventureWorksEntities db = new AdventureWorksEntities();
IQueryable _query = (from c in db.Address
where c.City.Equals("Bothell", StringComparison.CurrentCultureIgnoreCase)
select new
{
ID = c.AddressID,
Endereco = c.AddressLine1,
Cidade = c.City,
CaixaPostal = c.PostalCode
}
).OrderBy(o=>o.Endereco);
return RetornarDataTable(_query);
}
public static DataTable RetornarDataTable(IQueryable pObjQuery)
{
DataTable _dt = new DataTable();
//Cria o DataTable
foreach (var item in pObjQuery)
{
Type t = item.GetType();
PropertyInfo[] properties = t.GetProperties();
for (int i = 0; i < properties.Length; i++)
{
_dt.Columns.Add(properties[i].Name);
}
break;
}
IEnumerator en = (IEnumerator)pObjQuery.GetEnumerator();
//Popula o DataTable
while (en.MoveNext())
{
Type ten = en.Current.GetType();
PropertyInfo[] propertiesen = ten.GetProperties();
DataRow _dtrow = _dt.NewRow();
for (int i = 0; i < propertiesen.Length; i++)
{
object obj = propertiesen[i].GetValue(en.Current, new object[] { });
_dtrow[i] = obj;
}
_dt.Rows.Add(_dtrow);
}
return _dt;
}
A codificação é relativamente simples e de fácil implementação.
Até a Próxima...
Olá amigo, também sou apaixonado por C#, já te add nos favoritos, interessa fazer troca de links?
ResponderExcluirBoa Tarde a Todos,
ResponderExcluirSempre me interessei por C#.
Eu gostaria de algumas opiniões.
Vi um curso na Impacta. Segue Link: http://www.impacta.com.br/curso/C-Modulo-I.php
Estou querendo fazer.
Gostaria de algumas opiniões.
Agradeço.