PetaPoco - Como mapear um relacionamento Many-to-Many (simulação de Lazy Load)
Há algum tempo estou utilizando a micro ORM PetaPoco para alguns projetos pessoais, a grande vantagem é o desempenho, liberadade e facilidade de implementação.
Eu poderia utilizar Entity Framework ou NHibernate, que são mais parrudos e completos, e que inclusive uso em outros projetos, mas o objetivo é justamente descomplicar e deixar o funcionamento o mais leve possível.
O objetivo deste artigo é exemplificar de forma simples e tornar fácil o entendimento de algo que garimpei na Internet e vi muitos artigos, bons, ruins, completos, incompletos, outros bem direitos, outros com muitos frufrus.
Vamos exemplificar então, à começar com algumas definições básicas:
Fazendo uma analogia para facilitar o entendimento:
Um mapeamento many-to-many tem a característica de um agregado como coleção, na prática a maneira como isso ocorre é por "lazy load" (ou não) a lista dos agregados é carregada quando solicitada, não quando o objeto é instanciado.
A classe View é o ponto central do artigo.
Vejam que a propriedade Campos também está decorada com Ignore.
Lembrando que estamos contextualizados em uma instância de View, esta é uma simples query com inner join para a tabela de Campos para então montar a relação de Campos desta View, por isso o parâmetro this.Id (da view) para o IdView da tabela de agregação.
A execução desta query irá listar todos os Campos agregados da View em contexto.
Já esta linha fará as atribuições dos campos projetados pela query executada.
Por padrão do PetaPoco a execução desta query irá gerar uma lista de CampoView, a propriedade Campo (1) da classe CampoView irá fazer com que os campos projetados da tabela campos sejam atribuídos como instância automaticamente.
Resumo
Referências:
Eu poderia utilizar Entity Framework ou NHibernate, que são mais parrudos e completos, e que inclusive uso em outros projetos, mas o objetivo é justamente descomplicar e deixar o funcionamento o mais leve possível.
O objetivo deste artigo é exemplificar de forma simples e tornar fácil o entendimento de algo que garimpei na Internet e vi muitos artigos, bons, ruins, completos, incompletos, outros bem direitos, outros com muitos frufrus.
Vamos exemplificar então, à começar com algumas definições básicas:
- View - uma view, oras, então temos Título e outras propriedades que a formam.
- Campo - é um elemento que compõe uma View.
- CampoView - agregação de todos os Campos que compõem Views. Uma View exibe para o usuário um Campo para digitação de nome, outro para digitação de Valor e etc.
Fazendo uma analogia para facilitar o entendimento:
- Pedido de Venda = View.
- Produto = Campo.
- Itens do Pedido de Venda = CampoView.
Um mapeamento many-to-many tem a característica de um agregado como coleção, na prática a maneira como isso ocorre é por "lazy load" (ou não) a lista dos agregados é carregada quando solicitada, não quando o objeto é instanciado.
Então em se tratado de consulta a banco de dados pelas classes quando carregamos uma View é feita a consulta apenas na tabela relacionada, quando consultamos os Campos agregados à instância da View é feita uma consulta apenas para isso.
Mão na massa então
(não estou atentando para a definição da classe de forma correta ao PetaPoco)public class CampoView { public Guid IdView { get; set; } public Guid IdCampo { get; set; } [Ignore] public Campo Campo { get; set; } }
Veja que a classe CampoView possui a propriedade Campo (1) decorada com um Ignore do PetaPoco.
Dica: Propriedades decoradas com o atributo Ignore não participam das atribuições dinâmicas de campos feitas pelo PetaPoco em Query/Fetch.
public class Campo {public Guid Id { get; set; }public string Nome { get; set; }public int Largura { get; set; } }Nada demais na classe Campo.Dica: para quem não sabe o PetaPoco trabalha automaticamente com campos CHAR(36) em formato Guid sem precisarmos fazer conversões, quando atribuímos uma string no formato Guid ele já faz as conversões necessárias.
public class View {
public Guid Id { get; set; }public string Titulo { get; set; } [Ignore] public List<CampoView> Campos { get { var sql = PetaPoco.Sql.Builder .Append("SELECT camposviews.*, campos.*") .Append("FROM camposviews, campos") .Append("WHERE (campos.Id = camposviews.IdCampo)") .Append(" AND camposviews.IdView = @0", new object[] { this.Id }); var lista = SeuRepositorioPetaPoco.Query<CampoView, Campo>(sql); return lista.ToList(); } } }
A classe View é o ponto central do artigo.
Vejam que a propriedade Campos também está decorada com Ignore.
Detalhando a implementação
var sql = PetaPoco.Sql.Builder.Append("SELECT camposviews.*, campos.*") .Append("FROM camposviews, campos") .Append("WHERE (campos.Id = camposviews.IdCampo)") .Append(" AND camposviews.IdView = @0", new object[] { this.Id });
Lembrando que estamos contextualizados em uma instância de View, esta é uma simples query com inner join para a tabela de Campos para então montar a relação de Campos desta View, por isso o parâmetro this.Id (da view) para o IdView da tabela de agregação.
A execução desta query irá listar todos os Campos agregados da View em contexto.
var lista = SeuRepositorioPetaPoco.Query<CampoView, Campo>(sql);
Já esta linha fará as atribuições dos campos projetados pela query executada.
Por padrão do PetaPoco a execução desta query irá gerar uma lista de CampoView, a propriedade Campo (1) da classe CampoView irá fazer com que os campos projetados da tabela campos sejam atribuídos como instância automaticamente.
Resumo
- Três classes, pai, filho, agregação dos filhos do pai.
- Execução da query montando a agregação e atribuindo o resultado gerando instâncias.
Referências:
- http://www.toptensoftware.com/petapoco/
- http://blogs.lessthandot.com/index.php/desktopdev/mstech/csharp/petapoco-mapping-related-objects/
- http://www.toptensoftware.com/Articles/115/PetaPoco-Mapping-One-to-Many-and-Many-to-One-Relationships
Comentários
Postar um comentário