por Cesar Cassiano Schimanco

ASP.NET - Eval vs Performance

É muito comum ver DataBinder.Eval em Repeater, DataGrid e DataList, mas muitos não sabem que ele pode causar problemas de performance.
No artigo de hoje vou mostrar algumas alternativas ao DataBinder.Eval

O Eval é um método que usa Reflection em tempo de execução para descobrir o tipo de dado do DataItem. E isso pode causar visível lentidão quando o volume de dados é grande, inclusive a própria Microsoft não recomenda o uso dele devido a sobrecarga.
Mas para pequenos volumes de dados vai bem.

Mas o que acontece na prática?
Imagine um Repeater onde seu DataSource é uma tabela com 10 linhas e 5 colunas. Então você usa Eval para retornar o valor de cada coluna, isso representa 5 chamados a cada linha. Assim no final das 10 linhas você terá chamando o Eval 50 vezes.

Abaixo vou mostrar o uso comum do DataBinder.Eval.
O Eval requer 2 ou 3 argumentos.
1: A própria fonte de dados
2: Nome do campo/coluna
3: Formatação

Exemplos de uso:
Usando somente o Eval, que não é igual ao DataBinder.Eval.

<%# Eval("DataCadastro") %>

Resultado: 05/01/2013 14:27:06

DataBinder.Eval com 2 argumentos - fonte de dados e o campo - neste caso o campo DataCadastro refere-se a propriedade do objeto Pessoa.

<%# DataBinder.Eval(Container.DataItem,"DataCadastro") %>

Resultado: 05/01/2013 14:27:06

DataBinder.Eval com formatação de dados.

<%# DataBinder.Eval(Container.DataItem,"DataCadastro", "{0:D}") %>

Resultado: quarta-feira, 9 de janeiro de 2013
 

Alternativas ao DataBinder.Eval.
Vou mostrar basicamente 2 alternativas, ambas usando o Container.DataItem, uma no próprio .ASPX e outra no .CS (ItemDataBound).
Container.DataItem é onde estão contidos os dados da posição atual da coleção/lista, ou seja, corresponde a uma linha.
A tipagem do DataItem é determinada pelo tipo de DataSource, então se sua fonte de dados é List<String> o DataItem é string.
Para pegar as propriedades de um objeto, você terá que fazer antes a conversão para o respectivo tipo.
Vendo os exemplos vai ficar melhor de entender.

Uso de Container.DataItem com conversão explícita.

<%# ((Pessoa)Container.DataItem).DataCadastro %>

Container.DataItem com DataSet e DataTable.

<%@ Import Namespace="System.Data" %>
...
<asp:Repeater runat="server" ID="Repeater1">
	<ItemTemplate>
		<%#((DataRowView)Container.DataItem)["DataCadastro"]%>
	</ItemTemplate>
</asp:Repeater>  

Mover o Eval para o code behind usando o ItemDataBound

Default.aspx

<asp:Repeater runat="server" ID="Repeater1" OnItemDataBound="Repeater1_ItemDataBound">
    <ItemTemplate>
        <asp:Literal ID="litDataCadastro" runat="server" />
    </ItemTemplate>
</asp:Repeater> 

Default.aspx.cs

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
    {
        //Pegar o Container.DataItem e converter para o tipo de dados específico, no meu caso, o tipo é Pessoa.
        Pessoa pessoa = (Pessoa)e.Item.DataItem;
        //Encontrar o Literal no Repeater
        Literal litDataCadastro = (Literal)e.Item.FindControl("litDataCadastro");
        //Popular o literal com a data de cadastro já formatada
        litDataCadastro.Text = pessoa.DataCadastro.ToString("dd/MM/yyyy");
        //Retornará: 05/01/2013
    }
}

 

Faça download do projeto com vários exemplos aqui.

Comentários

Carregando comentários

Postar um novo comentário



Processando...