Este é o terceiro post de uma série de posts que estou escrevendo sobre a próxima versão da ASP.NET ( ASP.NET vNext ).
Os
próximos lançamentos do .NET e Visual Studio incluem vários novos e
ótimos recursos e capacidades. Com a ASP.NET vNext você vai ver um
monte de melhorias realmente emocionantes em formulários da Web ( Web
Forms ) e MVC - assim como no núcleo da base de código da ASP.NET, no
qual estas tecnologias são baseadas.
O post de hoje é o primeiro
de três posts que vou escrever durante a próxima semana que falam sobre o
novo suporte para Model Binding ( Ligação do Modelo Dados ) que está
chegando para Web Forms. Model Binding é uma extensão do sistema de
data-binding ( ligação de dados ) existente na ASP.NET Web Forms e
fornece um paradigma de acesso a dados focado no código. Este novo
suporte tira proveito de um monte de conceitos relativos à ligação do
modelo de dados que introduzimos pela primeira vez com a ASP.NET MVC - e os
integra muito bem com o modelo de controles do servidor para Web Forms.
Algumas informações sobre como a Ligação de Dados é feita hoje
Enquanto
Web Forms inclui uma série de controles de fonte de dados (por exemplo,
SqlDataSource, EntityDataSource, LinqDataSource) que permitem que você
conecte de forma declarativa controles do servidor diretamente a
datasources ( fontes de dados ), muitos desenvolvedores preferem manter o
controle total sobre a lógica de acesso a dados - escrevendo essa
lógica usando código.
Nas versões anteriores da tecnologia Web
Forms, isso poderia ser colocado em prática definindo a propriedade
DataSource de um controle diretamente, e, em seguida, chamando seu
método DataBind() a partir do arquivo code-behind da página. Enquanto
isso funciona em muitas situações, isso não funciona bem com controles
de dados mais ricos (como um GridView) que suportam operações
automáticas como sorting/ordenação, paging/paginação e editing/edição.
Outra
opção disponível hoje é usar o controle ObjectDataSource. Este controle
permite uma separação mais clara do código da interface gráfica ( UI )
do código da camada de acesso a dados, e permite que os controles de
dados forneçam funcionalidade automática, como paginação e ordenação. No entanto, enquanto o ObjectDataSource funciona bem para a seleção de
dados, ele ainda é complicado quando realizamos 2-way data-binding (
ligação de dados em duas direções/vias - leitura/escrita ), ele suporta
apenas propriedades simples (sem ligação/hierarquia "profunda" de tipos complexos) e
muitas vezes requer que os desenvolvedores escrevam uma grande
quantidade de código complexo para lidar com muitos cenários (incluindo
os comuns, como erros de validação).
Apresentando Model Binding ( Ligação do Modelo de Dados )
A ASP.NET vNext inclui novo suporte para "Model Binding" dentro de Web Forms.
Model
Binding pretende simplificar o trabalho com a lógica de acesso a dados
focada em código, mantendo os benefícios de um rico framework de ligação
de dados em 2 vias (leitura/escrita). Este novo suporte incorpora o
padrão de ligação do modelo de dados que nós introduzimos pela primeira vez com a
ASP.NET MVC, também mantendo uma boa integração com o modelo de
controles do servidor para Web Forms. Ele torna mais fácil executar
cenários comuns no estilo CRUD (Create/Criar, Retrieve/Retornar,
Update/Atualizar e Destroy/Deletar) com Web Forms - e permite que você
os execute usando qualquer tecnologia de acesso de dados (EF, LINQ para
SQL, NHibernate, DataSets, ADO.NET, etc).
Eu escreverei vários
posts esta semana que mostrarão como tirar proveito das novas
capacidades da ligação do modelo de dados. No post de hoje vou
demonstrar como utilizar a ligação do modelo de dados para recuperar dados - e
permitir a ordenação e paginação dos dados em um controle GridView.
Recuperando Dados usando o SelectMethod
Model
binding é uma abordagem centrada em código para data-binding. Ela
permite que você escreva métodos de ajuda CRUD dentro do arquivo
code-behind da sua página, e então facilmente os conecte a qualquer
controle do servidor dentro da página. Os controles do servidor, então,
tomarão o cuidado de chamar os métodos no momento apropriado durante o
ciclo de vida da página e farão a ligação dos dados.
Para ver
um exemplo simples de como isso funciona, vamos usar um controle
<asp:gridview>. O Gridview a seguir tem 4 colunas - 3 delas são
BoundFields padrão, e a quarta coluna é um TemplateField. Note como
definimos a propriedade ModelType no GridView para ser um objeto do tipo Category - isso habilita a ligação de dados fortemente tipada dentro do TemplateField (por exemplo: Item.Products.Count ao invés de usar o método de ajuda Eval()):
<asp:GridView ID="categoriesGrid" runat="server" ModelType="WebApplication1.Model.Category"
SelectMethod="GetCategories" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="CategoryID" HeaderText="ID" />
<asp:BoundField DataField="CategoryName" HeaderText="Name" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="# of Products">
<ItemTemplate><%# Item.Products.Count %></ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Configuramos o GridView para retornar seus dados usando Model Binding através da definição da propriedade SelectMethod
do GridView para apontar para o método GetCategories() que está dentro
do arquivo code-behind da página. Este método GetCategories() é
semelhante ao seguinte código:
public IQueryable<Category> GetCategories() {
var northwind = new Northwind();
return northwind.Categories.Include(c => c.Products);
}
Acima
eu estou usando EF Code First para executar uma consulta LINQ que
retorna uma lista de categorias do banco de dados de exemplo Northwind.
Note que não temos que realizar a consulta ao banco de dados dentro do
arquivo code-behind - eu poderia ter realizado essa consultada
alternativamente, dentro de um repositório ou de uma camada de acesso a
dados e depois simplesmente eu poderia ter usado o método de ajuda GetCategories() para
conectar o controle a ele.
Quando executamos a página, o GridView
irá chamar o método acima automaticamente para obter os dados e
renderizá-los na página igual a seguir:

Evitando Selects N+1
Uma coisa que você deve ter notado no código acima é que estamos usando o método de extensão .Include (c => c.Products)
na nossa consulta LINQ. Isto informa o EF para modificar a consulta de
forma que, além de recuperar as informações de Categoria, ele deve
incluir também os Produtos relacionados (evitando ter que realizar uma
nova consulta separada ao banco de dados para recuperar essas
informações para cada linha de Categoria retornada).
Suporte a Ordenação e Paginação
Poderíamos ter retornado as categorias em nosso método GetCategories() usando um IEnumerable<Category> - ou um tipo que implementa essa interface como List<Category>. Ao invés disso, porém, retornamos as categorias usando uma interface IQueryable<Category>:
public IQueryable<Category> GetCategories() {
var northwind = new Northwind();
return northwind.Categories.Include(c => c.Products);
}
O
benefício de retornar IQueryable<T> é que esta interface permite a execução
deferida (tardia) da consulta e permite que um controle vinculado aos
dados modifique a consulta antes de executá-la. Isso é particularmente
útil com os controles que suportam paginação e ordenação dos dados. Esses controles podem adicionar automaticamente os operadores de
ordenação e paginação apropriados em uma consulta IQueryable<T>
antes de executá-la. Isto tem a vantagem de tornar a ordenação e
paginação realmente fácil de ser implementada em seu código - bem como
garante que as operações de ordenação e paginação sejam feitas no banco
de dados de uma forma super eficiente.
Para ativar a ordenação e paginação em nosso GridView, vamos modificá-lo setando as propriedades AllowSorting e AllowPaging com true, e especificaremos o tamanho da página PageSize com 5. Vamos também especificar uma expressão de ordenação SortExpression apropriada em duas de nossas colunas:
<asp:GridView ID="categoriesGrid" runat="server" AutoGenerateColumns="false"
AllowSorting="true" AllowPaging="true" PageSize="5"
ModelType="WebApplication1.Model.Category"
SelectMethod="GetCategories">
<Columns>
<asp:BoundField DataField="CategoryID" HeaderText="ID" SortExpression="CategoryID" />
<asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="# of Products">
<ItemTemplate><%# Item.Products.Count %></ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
E agora, quando executamos a página, podemos paginar e ordenar os dados:

Apenas
as categorias visíveis na página ordenada atual serão retornadas do
banco de dados - isto porque o EF irá otimizar a consulta para executar a
operação de ordenação e paginação como parte da consulta do banco de
dados, e dessa forma não realizará essas operações na camada
intermediária dentro do código fonte. Isso faz com que a
ordenação/paginação seja eficiente mesmo com grandes quantidades de
dados.
Vídeo rápido sobre Model Binding e SelectMethods
Damian Edwards tem um ótimo video de 90 segundos
que mostra o uso de Model Binding para implementar um cenário com
GridView que habilita ordenação e paginação dos dados. Você pode
assistir ao vídeo de 90 segundos aqui.
Sumário
O
novo suporte a Model Binding na ASP.NET vNext é uma boa evolução do
sistema atual de ligação de dados em Web Forms. Este suporte toma
emprestado os conceitos e as características do sistema de Model Binding
presente na ASP.NET MVC (você verá mais sobre isso em futuros posts), e
torna o trabalho com paradigmas de acesso a dados focados em código
mais simples e mais flexível.
Em futuros posts nesta série eu
discutirei mais sobre Model Binding e olharei como podemos facilmente
integrar cenários de filtragem de dados em nossos cenários de seleção de
dados, e como devemos lidar com cenários de edição (incluindo aqueles
cenários que usam validação).
Espero que ajude,
Scott
P.S. Além do blog, eu uso o Twitter para disponibilizar posts rápidos e para compartilhar links. Meu apelido no Twitter é: @scottgu
Texto traduzido do post original por
Leniel Macaferi.