Voltar

Yamapper: objeto Criteria

Em Yamapper | 13/01/2012 15:09 Yamapper

O objeto Criteria é o cerne de todas as ações de filtragem de dados no Yamapper. A ideia é permitir uma maneira simples e orientada a objetos de definição de restrições para obtenções de dados independente de qual gerenciador de banco de dados esteja em utilização.

Utilização

Os métodos de obtenção (Get), exclusão (Delete), checagem de existência (Exists) e contagem de registros (Count) do objeto DbProvider podem receber como parâmetro um objeto Criteria para filtragem dos dados, como no exemplo abaixo:

provider.Get<Cliente>(Criteria.Create()
	.Add(Expression.Equal("IdCliente", idCliente)));

De modo geral, para utilização do objeto Criteria, obtenha sua instância a partir do método Create e adicione expressões de filtragem, ordenação e limitação de quantidade de registros a partir de seus métodos públicos:

O uso do objeto Criteria é recursivo, sendo que seus métodos sempre retornam sua instância atual para facilitar o aninhamento de expressões.

Expressões

Expressões são objetos que definem parâmetros de filtragem de dados no objeto Criteria. Para instanciá-las, utilize a factory Expression, a qual permite a criação de todos os tipos de expressões disponíveis.

Expressões simples

Expressões simples (geradas a partir do objeto SimpleExpression) permitem a realização de filtragens envolvendo os operadores de comparação básicos. A maioria dos métodos para criação dessas expressões recebem como parâmetro o campo que se deseja avaliar e o dado de comparação.

Expressões In e NotIn

As expressões In e NotIn permitem a comparação de um campo a um conjunto de valores. Ambas são métodos genéricos que devem receber o tipo do vetor de objetos o qual contém os dados a serem utilizados na filtragem.

provider.Get(Criteria.Create()
	.Add(Expression.In<string>("Nome"
		, new string[] { "Astrobaldo", "Bráulio", "Josisbaldo" })));

Expressões SQL

Expressões SQL permitem o envio de códigos SQL diretamente como parâmetro de filtragem, os quais serão anexados diretamente à clausula WHERE da instrução enviada ao banco de dados. Sua utilização pode ser feita com ou sem parâmetro. Caso haja parâmetro, a palavra reservada {param} deverá ser utilizada para indicar o local no qual deverá ser substituído o nome interno do parâmetro gerado. No exemplo abaixo, são retornados todas as pessoas que possuam nomes com a letra J:

provider.Get(Criteria.Create()
	.Add(Expression.Sql("Nome LIKE {param}", "%J%")));

Expressões lógicas

O uso de expressões lógicas permite o aninhamento de diversas expressões a partir de operadores lógicos, auxiliando na composição de filtragens mais complexas. Para utilizá-las, basta utilizar os métodos Expression.And ou Expression.Or, de acordo com o operador lógico desejado, para criar e aninhar expressões. A quantidade de expressões que pode ser aninhada é ilimitada. No exemplo abaixo, expressões AND são aninhadas em uma expressão OR para obtenção de registros de pessoas com determinados nomes e configurações de data:

provider.Get(Criteria.Create()
	.Add(Expression.Or(
		Expression.And(
			Expression.Equal("Nome", "Astrobaldo"),
			Expression.IsNull("DataCadastro"))
		, Expression.And(
			Expression.Equal("Nome", "Bráulio"),
			Expression.IsNotNull("DataCadastro"))
		, Expression.And(
			Expression.Equal("Nome", "Josisbaldo"),
			Expression.LesserThan("DataCadastro", DateTime.Now))
		)
	)
);

Criando suas próprias expressões

Para criar suas próprias expressões, basta programar uma classe que implemente a interface Intentor.Yamapper.IExpression, a qual possui um único método, string ToSqlString<T>(string parameterPrefix, List parameters), o qual deve ser utilizado para obter a expressão em formato SQL, preferencialmente independente de particularidades de um determinado banco de dados.

Paginação

A partir do uso do objeto Criteria é possível realizar paginação de dados através dos métodos Limit (quantidade máxima de registros a ser retornada) e Offset (índice do registro inicial para obtenção dos dados, começando em 0). O exemplo abaixo demonstra a utilização de tal procedimento em um método PageIndexChanging de um GridView:

protected void gvClientes_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
	//Obtém o GridView.
	var grv = ((GridView)sender);
	//Obtém o tamanho da página para paginação.
	int pageSize = grv.PageSize;

	//Cria o critério de paginação utilizando-se de OffSet e Limit.
	var crit = Criteria.Create()
		.Offset(e.NewPageIndex * pageSize) //Posição inicial.
		.Limit(pageSize); //Quantidade máxima de registros a ser obtida.
		
	//Popula o GridView.
	grv.PageIndex = e.NewPageIndex;
	grv.DataSource = Facade.GetByCriteria(crit)
						.BindTo<ClienteView, Cliente>();
	grv.DataBind();
}

Adicionalmente, pode-se também criar uma classe que, a partir do uso dos mesmos métodos, permita a paginação de dados:

public class ClientesDataSource
{
	private ClienteBiz _biz = new ClienteBiz(new ClienteDao());

	public int SelectCount()
	{
		return _biz.Count();
	}

	public List<ClienteView> Select(int maximumRows, int startRowIndex)
	{
		return _biz.GetByCriteria(Criteria.Create()
				.Offset(startRowIndex)
				.Limit(maximumRows)
			).BindTo<ClienteView, Cliente>();
	}
}

Para utilizá-la, crie um ObjectDataSource na página e vincule-o ao GridView, como no exemplo abaixo:

<asp:GridView ID="gvClientes" runat="server" DataSourceID="odsClientes"
	AllowPaging="True" PageSize="5" AutoGenerateColumns="false">
	<Columns>
		<asp:BoundField DataField="Nome" HeaderText="Cliente" />
	</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsClientes" runat="server" EnablePaging="True" 
	TypeName="Intentor.Examples.Web.ClientesDataSource" 
	SelectMethod="Select" 
	SelectCountMethod="SelectCount">
</asp:ObjectDataSource>

NOTA: o uso do extension method BindTo e um DataTransferObject se fazem necessários caso a classe que representa a entidade utilize LazyLoading, uma vez que o GridView tem problemas em interpretar corretamente proxy classes via Reflection

Ao infinito e além

O projeto de exemplo presente no código-fonte do Yamapper apresenta o uso do objeto Criteria de forma prática, reunindo diversos exemplos de sua utilização.

Caso tenha alguma dúvida, curiosidade, trauma ou angústia sobre o projeto, ou apenas deseja elogiá-lo, utilize o espaço de comentários mais abaixo para entrar em contato.

Comentários
Comentar
Campos marcados com * são obrigatórios. Seu e-mail não será exibido.
*
*
*
Captcha *
CATEGORIAS AO TOPO E ALÉM LUGARES PARA IR
Topo

“It feels like the number one enemy in any act of creation is time; there’s never enough of it. ” - Peter Cardwell-Gardner