Upload
humberto-marchezi
View
2.728
Download
10
Embed Size (px)
Citation preview
Programação OO com NHibernate
Agenda
Dia 1: Fundamentos de NHibernate
Para que serve ?
Quais as vantagens ?
O que é mapeamento objeto-relacional ?
Como funciona o mapeamento objeto-relacional no NHibernate ?
Exercícios (Mapeando uma classe simples – apenas propriedades)
Programação OO com NHibernate
Agenda
Dia 2: Associações no NHibernate
Como implementar uma associação vários-para-um (simples) ?
Exercício
Como implementar uma associação vários-para-um (posse) ?
Exercício
Como implementar uma associação um-para-vários ?
Exercício
Programação OO com NHibernate
Agenda
Dia 3: Associações no Nhibernate e Herança
Como implementar uma associação vários-para-vários ?
Exercício
Herança
Uma Tabela para cada Classe
Exercício
Uma Tabela para Toda a Herança
Exercício
Programação OO com NHibernate
Agenda
Dia 4: Objetos de Valor
Objetos de Valor e Entidades
Como implementar um objetos de valor
Exercício
Fundamentos de NH
Para que serve ? Automatizar a relação entre dois mundos: As tabelas/visões do banco relacional ( dados )
As classes do mundo dos objetos ( domínio do problema )
NHibernate
Modelo de Objetos Modelo de Dados
class Documento
class PessoaFisica
class Endereco
class TipoDocumento
session .SaveUpdate(p);
session .Remove(p);
selectinsertupdateremove
table Documento
table PessoaFisica
table Endereco
table TipoDocumento
Fundamentos de NH
Para que serve ? Geração Automática de Comandos SQL
TipoDocumento tp = new TipoDocumento();tp.Descricao = “Tipo Doc Qualquer”;
insert into Geral_TipoDocumento( descricao ) values( “Tipo Doc Qualquer” )
tp.Descricao = “Outro Tipo Doc”;update Geral_TipoDocumento tpset tp.descricao = “Outro Tipo Doc”where tp.codTipoDocumento = 12
select tp.codTipoDocumento, tp.descricaofrom Geral_TipoDocumento tpwhere tp.codTipoDocumento = 12
session.SaveOrUpdate(tp);
delete Geral_TipoDocumento where tp.codTipoDocumento = 12
TipoDocumento tp = session .Get<TipoDocumento>(12);
session.SaveOrUpdate(tp);
session.Delete(tp);
Fundamentos de NH
Vantagens POO – Abstrair
complexidade das regras de negócio (Escrever código que parece fácil)
Isso (Programação OO)
PessoaFisica p=new PessoaFisica( nome, new DocumentoCPF(numCPF), new Endereco(numCEP, numEndereco)); session.Save(p);
Ao invés disso (Programação comum)
if (nome == string.Empty){ throw new Exception(“nome vazio”);}if (numCPF == null){ throw new Exception(“cpf não foi informado”);}......... Lógica para validar o CPF..........if (numCEP == null){ throw new Exception(“CEP não informado”);}............. Lógica para validar o CEP ............................ Lógica para trazer endereco pelo CEP..string sql = “insert into Pessoa (nome, cpf, numero, cep, codLogradouro, codBairro, codLocalidade, codEstado, codPais) values (“nome + ”,” + cpf + ”,” + numero + ”,” + cep + ”,” + codLogr.................................SqlCommand sql = new SqlCommand(sql);.......... Continua e nem cabe aqui o código .......
Fundamentos de NH
Vantagens Essa relação não precisa ser 1 classe = 1
tabela havendo um espaço para flexibilidade entre os dois modelos
Modelo de Objetos Modelo de Dados
Pessoa
Pessoa Pessoa
Documento
Taxa
ValorFinanceiro
TabPessoa
TabDocumento
TabDocumento
Fundamentos de NH
Vantagens Permite que o DBA se concentre na melhor
forma de modelar os dados e os Analistas/Programadores se concentrem na melhor forma de representar as entidades e regras do problema a ser modelado
Fundamentos de NH
Vantagens Classes podem ser escritas em C# puro sem
qualquer tipo de implementação específica como herdar de classe específica ou interfacepublic class ImpostoX
{ protected decimal _valor; protected ImpostoX() { } public ImpostoX(decimal valor) { _valor = valor; } public decimal Valor { get { return _valor; } }}
public class ImpostoX{ protected decimal _valor; public ImpostoX() { } public decimal Valor { get { return _valor; } set { _valor = value; } }}
public class ImpostoX{ protected decimal _valor; public ImpostoX() { } public void AtribuirValor (decimal valor) { _valor = valor; } public decimal ObterValor( ) { return _valor; }}
Fundamentos de NH
Vantagens Reuso de código ao invés de copy/paste Garantia de qualidade: testes unitários Legibilidade, manutenibilidade, extensibilidade, etc.
Fundamentos de NH
O que é mapeamento objeto-relacional ? Técnica que consiste em traduzir (criar um tipo
“de .... - para ... “) entre as classes e suas propriedades no modelo-de-objetos e as tabelas/visões e suas colunas no modelo de dados
No NHibernate esse mapeamento é feito através de arquivos no padrão XML ( *.hbm.xml )
A partir desses arquivos, o NHibernate sabe como gerar os SQLs automatizados para as classes
Fundamentos de NH
O que é mapeamento objeto-relacional ?
public class TipoHistorico{
protected TipoHistorico( ) { } public TipoHistorico (string descricao) { _descricao = descricao; } protected long _id; public long Id { get { return _id; } set { _id = value; } } protected string _descricao; public string Descricao { get { return _descricao; } set { _descricao = value; }}
tabela Geral_TipoHistorico
codTipoHistorico int PK
descricao varchar(50)
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
TipoDocumento.cs
using System;
namespace ControleCorporativo.ControleGeral.DP{
public class TipoDocumento{
private long _id;public long Id{ get { return _id; } set { _id = value; } }
private string _descricao;public string Descricao{ get { return _descricao; } set { _descricao =
value; } }}
}
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Tabela Geral_TipoDocumento
create table Geral_TipoDocumento(
codTipoDocumento INT primary key,descricao varchar(60)
)
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
TipoDocumento.hbm.xml
<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio">
<class name="ControleCorporativo.ControleGeral.DP.TipoDocumento" table="Geral_TipoDocumento">
<id name="Id" column="codTipoDocumento"><generator class="identity"/>
</id>
<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>
</class></hibernate-mapping>
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Configuração: ( necessário na primeira vez )Criando uma classe de configuração para o NHibernate
using System;using NHibernate.Cfg;
namespace SistemaX.Persistencia { public class ConfiguracaoNH { public static Configuration CriarConfiguracao() { Configuration config = new Configuration(); config.Properties["query.substitutions"] = "true 1,false 0"; config.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider"; config.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect"; config.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";config.Properties["connection.connection_string"] = "server=Colibri\\SQL2005;database=bdcurso;user id=usr_aluno;"+ "password=aluno;connect timeout=60"; config.AddAssembly("SistemaX.Dominio"); return config; } }}
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Configuração: ( necessário na primeira vez )Criando um singleton para a ISessionFactory (NHibernateHelper.cs)
using NHibernate;
namespace SistemaX.Persistencia{ public class NHibernateHelper { // A ISessionFactory é unica para toda a aplicação e // é responsável por processar todos os mapeamentos // do NHibernate private static readonly ISessionFactory sessionFactory = ConfiguracaoNH.CriarConfiguracao().BuildSessionFactory();
public static ISessionFactory ObterSessaoFactory() { return sessionFactory; } }}
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Inserindo
// Abre a sessao com o bancoISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();
// Cria um tipo de documentoTipoDocumento tp = new TipoDocumento() { Descricao = “Novo Tipo Documento” };
// Inicia TransaçãoITransaction tx = sessao.BeginTransaction();
// Salva o tipo de documentosessao.Save(tp);
// Confirma Transaçãotx.Commit();
// Fecha a sessão com o bancosessao.Close();
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Alterando
// Abre a sessao com o bancoISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();
// Cria um tipo de documentoTipoDocumento tp = sessao.Get<TipoDocumento>(10);
// Inicia TransaçãoITransaction tx = sessao.BeginTransaction();
// Salva o tipo de documentosessao.Update(tp);
// Confirma Transaçãotx.Commit();
// Fecha a sessão com o bancosessao.Close();
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Removendo
// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();
// Inicia uma transaçãoITransaction transacao = session.BeginTransaction();
// Recupera um tipo de documento com chave = 10TipoDocumento tipoDocumento = session.Get<TipoDocumento>(10);
// Deletando um tipo de documentosession.Delete(tipoDocumento);
// Confirma a transaçãotransacao.Commit();
// Fecha a sessão com o bancosession.Close();
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Consultando (com HQL)
// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();
// Executa uma consulta em HQL, resultado como lista de objetosstring strHQL = “from TipoDocumento tp where tp.Descricao like '%CP%'”;IList<TipoDocumento> lstResultado = session.CreateQuery(strHQL)
.List<TipoDocumento>();
string strMensagem = string.Empty;foreach(TipoDocumento tp in lstResultado){
strMensagem += “ Id = “ + tp.Id + “ Desc = “ + tp.Descricao + “\n”;}
MessageBox.Show(strMensagem);
// Fecha a sessão com o bancosession.Close();
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Consultando (com HQL)
// Abre uma sessão com o bancoISession session = NHibernateHelper.ObterSessaoFactory().OpenSession();
// Executa uma consulta em HQL, resultado como lista de objetosIList<TipoDocumento> lstResultado = (from tp in session.Linq<TipoDocumento>()
where tp.Descricao.Contains(“CP”)
select tp).ToList();
string strMensagem = string.Empty;foreach(TipoDocumento tp in lstResultado){
strMensagem += “ Id = “ + tp.Id + “ Desc = “ + tp.Descricao + “\n”;}
MessageBox.Show(strMensagem);
// Fecha a sessão com o bancosession.Close();
Fundamentos de NHibernate
Como funciona o mapeamento objeto-relacional no NHibernate ?
Template de mapeamento<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2 " assembly="[DLL onde está a classe] " namespace="[namespace da classe (using)] ">
<class name="[nome da classe] " table="[nome da tabela] " lazy="true"> <id name="[propriedade de id] " column="[chave primária] " type="[nome do tipo na classe] "> <generator class="[ native | identity | sequence | assigned | outros ] "/> </id>
<property name="[campo1 da classe] " type="[tipo na classe] " column="[coluna1 na tabela] " accessor ="field.camelcase-underscore " /><property name="[campo2 da classe] " type="[tipo na classe] " column="[coluna2 na tabela] " accessor ="field.camelcase-underscore " /><property name="[campo3 da classe] " type="[tipo na classe] " column="[coluna3 na tabela] " accessor ="field.camelcase-underscore " /> : : : : : : : : : : : : <property name="[campoN da classe] " type="[tipo na classe] " column="[colunaN na tabela]"accessor ="field.camelcase-underscore " />
</class>
</hibernate-mapping >
Fundamentos de NHibernate
Exercício Dada a classe Pessoa ( em pseudo código ) e a tabela Pessoa abaixo, criar uma mini-
aplicação web de cadastro utilizando NHibernate.
class Orgao { public long Id {get;set;}; public string Descricao {get;set;}; }
create table Orgao (codOrgao INT primary key, descricao varchar(50) NOT NULL )
Campos da mini aplicação web: Nome:
Id:
Id: Nome:
txtDescr
Incluir
txtDescr
Pesquisar
ListBox
txtId Remover
txtId AlterartxtDescr
Associações no NHibernate
Convenção para notação de classes em C#.NETTipoDocumento.cs (Completo) TipoDocumento.cs (Simplificado)
using System;namespace ControleCorporativo.ControleGeral.DP{
public class TipoDocumento{
private long _id;public virtual long Id{
get { return _id; }protected set { _id = value; }
}private string _descricao;public string Descricao{
get { return _descricao; }set { _descricao = value; }
}}
}
public class TipoDocumento{
public long Id { get; set; }public string Descricao {get;
set; }}
Associações no NHibernate
Como implementar mapeamento sem associacões ?C#.NET SQL
public class Orgao{ public long Id { get; set; } public string Descricao {get; set;}}
create table Orgao( codOrgao INT primary key, descricao varchar(50))
Orgao.hbm.xml
<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio"> <class name="SistemaX.Dominio.Orgao" table="Orgao">
<id name="Id" column="codOrgao"> <generator class="identity"/> </id>
<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>
</class>
</hibernate-mapping>
Associações no NHibernate
Associação vários-para-um (Associação)
C#.NET SQL
public class Pessoa{
public long Id { get; set; }public string Nome { get; set; }public Orgao Lotacao { get; set; }
}
public class Orgao{
public long Id { get; set; }public string Descricao { get; set; }
}
create table Pessoa(
codPessoa INT primary key,nome varchar(50),codOrgao INT
)
create table Orgao(
codOrgao INT primary key,descricao varchar(50)
)
Associações no NHibernate
Associação vários-para-um (Associação)
<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[assembly]">
<class name="SistemaX.Dominio.Pessoa" table="Pessoa">
<id name="Id" column="codPessoa"><generator class="identity" />
</id>
<property name="Nome" column="nome" access="field.camelcase-underscore"/>
<many-to-one name=”Lotacao” class="Orgao" column=”codOrgao” access="field.camelcase-underscore"/>
</class></hibernate-mapping>
Pessoa.hbm.xml
Associações no NHibernate
Associação vários-para-um (Associação)
Exemplo de código C# para alteração do Orgão onde uma Pessoa esta lotada:
ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction();
// Obtem um orgao do banco-de-dadosOrgao orgao = sessao.Get<Orgao>((long)45);
// Cria uma nova pessoaPessoa p = sessao.Get<Pessoa>((long)70);
p.Lotacao = orgao; // Salva a pessoasessao.Save(p);
trans.Commit();sessao.Close();
Associações no NHibernate
Exercício (vários-para-um) (associação) Incluir Pessoa
Nome txtNome Orgao cmbbxOrgao
Alterar Pessoa
Pelo Id txtIdPessoa Nome txtNome Orgao cmbbxOrgao
Remover Pessoa
Pelo Id txtIdPessoa
Incluir
Alterar
Remover
Associações no NHibernate
Associação vários-para-um (composição)C#.NET SQL
public class Pessoa{
public long Id { get; set; }public string Nome { get; set; }private Endereco _endereco =
new Endereco();public Endereco Endereco { get; }
}
public class Endereco{
public long Id { get; set; }public string Localidade { get; set; }
}
create table Pessoa(
codPessoa INT primary key,nome varchar(50),codEndereco INT
)
create table Endereco(
codEndereco INT primary key,
localidade varchar(50))
Associações no NHibernate
Associação vários-para-um (Posse)
<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[assembly]">
<class name="SistemaX.Dominio.Pessoa" table="Pessoa">..................... outros mapeamentos ..........................
<many-to-one name=”Endereco” class="Endereco" column=”codEndereco” access="field.camelcase-underscore" cascade="all"/>
</class></hibernate-mapping>
Pessoa.hbm.xml
Endereco.hbm.xml
<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio">
<class name="SistemaX.Dominio.Endereco" table="Endereco">
<id name="Id" column="codEndereco"> <generator class="identity"/> </id>
<property name="Localidade" column="localidade" access="field.camelcase-underscore"/>
</class></hibernate-mapping>
Associações no NHibernate
Associação vários-para-um (Posse)ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction();
Exemplo de código C# para inclusão de Pessoa com Endereco:
// Cria uma nova pessoa com EnderecoPessoa p = new Pessoa( ) p.Nome=”Nova Pessoa”;p.Endereco.Localidade = “Anchieta”;sessao.Save(p);
Exemplo de código C# de alteração de endereço de uma Pessoa existente no banco:
// Alterando a localidade de uma pessoa grvada em bancoPessoa p2 = sessao.Get<Pessoa>((long)70);p2.Endereco.Localidade = “Outra Localidade”;sessao.Update(p);
trans.Commit();sessao.Close();
Associações no NHibernate
Exercício (associação vários-para-um) Incluir Pessoa
Id da Pessoa txtIdPessoa Nome txtNome Localidade txtLocalidade
Alterar Pessoa
Id da Pessoa txtIdPessoa Nome txtNome Localidade txtLocalidade
Remover Pessoa
Id da Pessoa txtIdPessoa
Incluir
Alterar
Remover
Associações no NHibernate
Associação um-para-vários C#.NET
SQLpublic class Pessoa{ public long Id { get; set; } public string Nome { get; set; } private IList<Documento> _documentos = new List<Documento>(); public IList<Documento> Documentos { get; }}
public class Documento{ public long Id { get; set; } public string Numero { get; set; } public Pessoa Pessoa { get; }}
create table Pessoa( codPessoa INT primary key, nome varchar(50))
create table Pessoa_Documento( codDocumento INT primary key, numero varchar(50), codPessoa int)
Associações no NHibernate Associação um-para-vários
Documento.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[DLL]" namespace="[namespace]">
<class name="DocumentoPessoa" table="Pessoa_DocumentoPessoa" lazy="true"><id name="Id" column="codDocumentoPessoa" type="Int64">
<generator class="identity" /></id><property name="numero" column="numero" type="string" access="field.camelcase-underscore"/>
<many-to-one name="relPessoa" class="Pessoa" column="codPessoa" access="field.ca..." not-null="true"/> </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio"> <class name="SistemaX.Dominio.Pessoa" table="Pessoa">
: : : outros mapeamentos : : : : : <bag name="Documentos" access="field.camelcase-underscore" cascade="all-delete-orphan" inverse="true"> <key column="codPessoa"/> <one-to-many class="SistemaX.Dominio.Documento"/> </bag>
</class></hibernate-mapping>
Pessoa.hbm.xml
Associações no NHibernate
Associação um-para-vários
Exemplo de código C# para inclusão de Documento em Pessoa Existente no Banco
ISession sessao = NHibernateHelper.ObterSessaoFactory().OpenSession();ITransaction trans = sessao.BeginTransaction(); // Obtem uma pessoa do banco-de-dadosPessoa p = sessao.Get<Pessoa>((long)44); // Adiciona um documento na PessoaDocumento d = new Documento() { Numero = “00009900” , Pessoa = p };p.Documentos.Add(d); // Altera o primeiro documento da Pessoap.Documentos[0].Numero = “000900”;// Remove o terceiro documento da Pessoap.Documentos.Remove( p.Documentos[2] );
// Salva a pessoa e todas alterações nos documentos de uma só vezsessao.Update(p);
trans.Commit();sessao.Close();
Associações no NHibernate
Exercício (associação um-para-vários) Incluir Documento
Id da Pessoa txtIdPessoa Desc. Doc. txtDescrDocumento
Alterar Documento
Id da Pessoa txtIdPessoa Id do Doc. txtIdDoc Desc.doc. txtDescrDocumento
Remover Documento
Id da Pessoa txtIdPessoa Id do Doc. txtIdDoc
Incluir
Alterar
Remover
Associações no NHibernate
Associação vários-para-vários
C#.NET SQLpublic class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}
public class Tarefa{ public long Id { get; set; } public string Descricao {get; set;} public IList<Pessoa> Pessoas {get; set;}}
create table Pessoa( codPessoa INT primary key, nome varchar(50) )
create table PessoaTarefa( codPessoa INT, codTarefa INT)
create table Tarefa( codDocumento INT primary key, descricao varchar(50), codPessoa INT)
Associações no NHibernate Associação vários-para-vários
<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio">
<class name="SistemaX.Dominio.Tarefa" table="Tarefa" lazy="true">
<id name="Id" column="codTarefa"> <generator class="identity"/> </id>
<property name="Descricao" column="descricao" access="field.camelcase-underscore"/>
<bag name="Pessoas" table="Pessoa_Tarefa" access="field.camelcase-underscore" lazy="true" inverse = "false" cascade="all"> <key column="codTarefa"/> <many-to-many class="SistemaX.Dominio.Pessoa" column="codPessoa"/> </bag>
</class>
</hibernate-mapping>
Tarefa.hbm.xml
Associações no NHibernate
Exercício (associação Vários-para-vários) Incluir Tarefa
Nome txtDescricao
Alterar Tarefa
Pelo Id txtIdTarefa Descricao txtDescricao
Remover Tarefa
Pelo Id txtIdTarefa
Incluir Pessoa na Tarefa
Tarefa txtIdTarefa Pessoa txtIdPessoa
Remover Pessoa da Tarefa
Tarefa txtIdTarefa Pessoa txtIdPessoa
Incluir
Alterar
Remover
Incluir
Remover
Associações no NHibernate Template de mapeamento: (Resumo)
Template de classe
using System;namespace AlgumNamespace{
public class AlgumaClasse {
private long _id;public virtual long Id { get { return this._id; } protected set { this._id = value; } }
protected tipo _campo; public virtual tipo Campo
{ get { return this._campo; } set { this._campo = value; } }
protected OutraClasse _associacao; public virtual OutraClasse Associacao
{ get { return this._associacao; } set { this._associacao = value; } }
protected IList<MaisOutraClasse> _associacaoLista; public virtual IList<MaisOutraClasse> AssociacaoLista
{ get { return this._associacaoLista; } set { this._associacaoLista = value; } } } }
Associações no NHibernate Template de mapeamento: (Resumo)
Template de mapeamento<?xml version="1.0" encoding="utf-8" ?><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2 " assembly="[DLL da classe] " namespace="[namespace] "> <class name="[nome da classe] " table="[nome da tabela] " lazy="true"> <id name="[propriedade de id] " column="[chave primária] " type="[tipo na classe] "> <generator class="[ native | identity | sequence | assigned | outros ] "/> </id>
<property name="[campo da classe] " type="[tipo do campo] " column="[coluna na tabela] " accessor="field.camelcase-underscore " />
<many-to-one name="[assoc. da classe] " class="[tipo da assoc.] " column="[chaveFK] " cascade="[none | all | save-update] " access="field.camelcase-underscore" />
<bag name="[lista na classe] " lazy="true" cascade="[ all-delete-orphan | save-update | none ] " inverse="true" access="field.camelcase-underscore"> <key column="[chave FK na tabela filho] "/>
<one-to-many class="[tipo de cada elemento na lista1] "/> </bag>
<bag name="[lista da classe] " table="[tabela agregada da associac.] " lazy="true" access="field.camelcase-underscore" cascade="[ all-delete-orphan | save-update | none ] ">
<key column="[chave FK para a tabela filho] "/><many-to-many class="[tipo de cada elemento na listaN+1] " column="[chave FK para a tabela pai] "/>
</bag>
</class></hibernate-mapping >
HerançaEstrutura em árvore composta por uma classe pai (genérica) e as classes filhas (específicas)Herança de classe pode ter várias formas no Modelo de DadosUma tabela para toda a hierarquia de classesUma tabela por classeUma tabela cada cada classe concreta
Herança Uma tabela para toda a hierarquia Modelo de Classe Modelo de Dados
create table Pessoa( codPessoa INT primary key, nome varchar(50), sexo char, objetoSocial varchar(50), tipoPessoa char)
public abstract class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}
public class PessoaFisica : Pessoa{ public char Sexo { get; set; }}
public class Pessoa Juridica : Pessoa{ public string ObjetoSocial { get; set; }}
Herança Uma tabela para toda a hierarquia
Pessoa.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio">
<class name="SistemaX.Dominio.Pessoa" table="Pessoa" lazy="true"><id name="Id" column="codPessoa" type="Int64">
<generator class="identity" /></id><discriminator column=”tipoPessoa” type=”char”/><property name="Nome" column="nome" type="string" access="field.camelcase-underscore"/>
</class></hibernate-mapping>
PessoaFisica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">
<subclass name=”PessoaFisica” discriminator-value=”f” extends="Pessoa"><property name=”CPF” column=”cpf” access="field.camelcase-underscore"/>
</subclass></hibernate-mapping>
PessoaJuridica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">
<subclass name=”PessoaJuridica” discriminator-value=”j” extends="Pessoa"><property name=”CNPJ” column=”cnpj” access="field.camelcase-underscore"/>
</subclass></hibernate-mapping>
Herança Uma tabela por classe Modelo de Classe Modelo de Dados
create table Pessoa( codPessoa INT primary key, nome varchar(50), )
create table PessoaFisica( codPessoa INT primary key, sexo char(50),)
create table PessoaJuridica( codPessoa INT primary key, objetoSocial varchar(50),)
public abstract class Pessoa{ public long Id { get; set; } public string Nome { get; set; }}
public class PessoaFisica : Pessoa{ public char Sexo { get; set; }}
public class Pessoa Juridica : Pessoa{ public string ObjetoSocial { get; set; }}
Herança Uma tabela por classe
Pessoa.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" >
<class name="SistemaX.Dominio.Pessoa" table="Pessoa" lazy="true"><id name="Id" column="codPessoa" type="Int64">
<generator class="identity" /></id><property name="Nome" column="nome" type="string" access="field.camelcase-
underscore"/></class>
</hibernate-mapping>
PessoaFisica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">
<joined-subclass name=”PessoaFisica” table=”PessoaJuridica” lazy="true" extends="Pessoa"><key column=”codPessoa”/><property name=”Sexo” column=”sexo” access="field.camelcase-underscore"/>
</joined-subclass></hibernate-mapping>
PessoaJuridica.hbm.xml<?xml version="1.0" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="SistemaX.Dominio" namespace="SistemaX.Dominio">
<joined-subclass name=”PessoaJuridica” table=”PessoaJuridica” lazy="true" extends="Pessoa"><key column=”codPessoa”/><property name=”ObjetoSocial” column=”objetoSocial” access="field.camelcase-underscore"/>
</joined-subclass></hibernate-mapping>
HerançaExercício (Herança -> 1 tabela para a hierarquia )Escrever um mapeamento NHibernate para a herança de documentos abaixo:
Fazer uma tela web de consultar objetos via HQL:
txtHQL btExecutar
listBoxResultado
public class Documento{
public long Id { get; set; }public string Numero { get; set; }
}public class DocumentoCI : Documento{
public string Estado { get; set; }}public class DocumentoCNH : Documento{
public string Categoria { get; set; }}
create table Documento(
codDocumento INT primary key,
numero varchar(50),estado varchar(50),categoria varchar(50),tipoDocumento varchar(50)
)
HerançaExercício (Herança ->1 tabela por classe)
Utiliar a mesma tela web de consulta para verificar os mapeamentos
txtHQL btExecutar
listBoxResultado
public abstract class Pessoa{
public long Id { get; set; }...
}public class PessoaFisica : Pessoa{
public string Sexo { get; set; }}public class PessoaJuridica : Pessoa{
public string ObjetoSocial { get; set; }}
create table Pessoa(
codPessoa INT primary key,...
)create table PessoaFisica(
codDocumento INT,sexo varchar(50)
)create table PessoaJuridica(
codDocumento INT,objetoSocial varchar(50)
)
Objetos de Valor e Entidades
Entidade: Toda classe cujo objeto precisa de um Id para identif.
Normalmente esta mapeada para 1 ou mais tabelas
Ex: Pessoa, Logradouro, InscricaoCadastral
Objeto de Valor:
Também é classe mas não possui Id de identificação
Representa um conceito importante do negócio
É imutável, não pode ser alterado, apenas subtituído
Ex: Dinheiro (valor + unid. Ref.), Endereco (alguns casos)
Objetos de Valor e Entidades Exemplo:
Modelo de Dados Modelo de Classes
create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))
create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))
public class Taxa{
public long Id { get; set; }public string Descricao { get; set; }public UnidadeReferencia
UnidadeReferencia { get; set; } public decimal ValorTaxa { get; set; }}
public class UnidadeReferencia{
public long Id { get; set; }public string Descricao { get; set; }
}
Objetos de Valor e Entidades Exemplo: (Funciona, mas vamos pensar melhor ... )
Modelo de Dados Modelo de Classes
create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))
create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))
public class Taxa{
public long Id { get; set; }public string Descricao { get; set; }public UnidadeReferencia
UnidadeReferencia { get; set; } public decimal ValorTaxa { get; set; }}
public class UnidadeReferencia{
public long Id { get; set; }public string Descricao { get; set; }
}
Objetos de Valor e Entidades Exemplo: (Vamos pensar melhor ... )
Modelo de Dados Modelo de Classes
create table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))
create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))
Essas duas colunas aparecem juntasem várias tabelas sugerindo um conceito importante de valor financeiro.
Objetos de Valor e Entidades Exemplo: ( Incluir conceito de negócio )
Modelo de Dados Modelo de Classescreate table Taxa( codTaxa INT primary key, descricao varchar(50), codUnidadeReferencia INT, valorTaxa numeric(12,4))
create table UnidadeReferencia( codUnidadeReferencia INT primary key, descricao varchar(50))
public class Taxa{
public long Id { get; set; }public string Descricao { get; set; }public ValorFinanc Valor { get; set; }
}public class ValorFinanc{ public ValorFinanc (UnidadeReferencia uf, decimal v) public UnidadeReferencia { get; } public decimal Valor { get; } public ValorFinanc static Adicionar( ValorFinanc fator1, ValorFinanc fator2, UnidadeReferencia result); public ValorFinanc static Subtr( ValorFinanc subtraendo, ValorFinanc subtrator, UnidadeReferencia result); public ValorFinanc Conversao(UnidadeReferencia result);}public class UnidadeReferencia{
public long Id { get; set; }public string Descricao { get; set; }
}
Objetos de Valor e Entidades Exemplo: ( Incluir conceito de negócio )
Mapeamento da classe Taxa<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="[DLL]" namespace="[namespace]">
<class name="Taxa" table="Taxa" lazy="true">
<id name="Id" column="codTaxa" type="Int64"><generator class="identity"/>
</id>
<property name=“Descricao" type="String" column="descricao" not-null="true" accessor="field.camelcase-underscore" />
<component name=“Valor” class=“ValorFinanc”><property name=“Valor” type=“String” column=“valorTaxa”/><many-to-one name=“UnidadeReferencia”
class=“UnidadeReferencia” column=“codUnidadeReferencia”/>
</component>
</class></hibernate-mapping>
Exercício
class PessoaEspecial{
public long Id { get; set; }public long Nome { get; set; }public EnderecoEspecial Endereco{ get; }
}
class EnderecoEspecial{
public string Localidade { get; set; }public string Numero { get; set; }
}
create table PessoaEspecial(
codPessoaEspecial INT primary key,
nome varchar(50),localidade varchar(50),numero varchar(50)
)
Mapear a classe PessoaEspecial
Testar a inclusão e a consulta de uma pessoa especial em C#
ObservaçõesProjeto Fluent Nhibernate permite escrever mapeamentos em C#
1. <?xml version="1.0" encoding="utf-8" ?> 2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 3. namespace="QuickStart" assembly="QuickStart"> 4. 5. <class name="Cat" table="Cat"> 6. <id name="Id"> 7. <generator class="identity" /> 8. </id> 9. 10. <property name="Name"> 11. <column name="Name" length="16" not-null="true" /> 12. </property> 13. <property name="Sex" /> 14. <many-to-one name="Mate" /> 15. <bag name="Kittens"> 16. <key column="mother_id"/> 17. <one-to-many class="Cat"/> 18. </bag> 19. </class> 20. </hibernate-mapping>
1. public class CatMap : ClassMap<Cat> 2. { 3. public CatMap() 4. { 5. Id(x => x.Id); 6. Map(x => x.Name) 7. .WithLengthOf(16) 8. .Not.Nullable(); 9. Map(x => x.Sex); 10. References(x => x.Mate); 11. HasMany(x => x.Kittens); 12. } 13. }
Observações
Consultas em Linq-to-NHibernate
Recursos geo-espaciais (MsSQLSpatial, PostGIS)
IList<TipoDocumento> lstResultado = (from tp in session.Linq<TipoDocumento>() where tp.Descricao.Contains(“CP”) select tp).ToList();
// Encontra um país localizado em uma coordenadaCountry country = session.CreateCriteria(typeof(Country)) .Add(SpatialExpression.Contains("Boundaries", new Point(-70.40, -33.24))) .UniqueResult() as Country;
// Encontra as cidades de uma área exceto aquelas localizadas em algumas coords.Town[] towns = Town.FindAll( SpatialExpression.Filter("Boundaries", new Envelope(-70, -68, -32, -34)), Expression.Not(SpatialExpression.Contains("Boundaries", new Point(-70.40, -33.24))));
Observações
Vantagens só aparecem com Programação OO
Pessoa p = new Pessoa(strNome,new DocumentoCPF(strCPF),new Endereco(strCEP));
session.SaveOrUpdate(p);
if ((strNome == null)||(strNome == string.Empty)){ .....Erro ... }if ((strCPF == null)||(strCPF == string.Empty)){ ... Erro ... }if ((strCEP == null)||(strCEP == string.Empty)){ ... Erro ... }IList<Pessoa> lstPessoas = ... consulta para achar ... outra pessoa com ... mesmo nome e CPFif (lstPessoas.Count > 0) { ..... Erro ......... }CEP cep = ... consulta de CEP pelo numeroif (cep == null ) { ........ Erro ....... }Localidade localidade = cep.Localidade;Pessoa p = new Pessoa( );p.Nome = strNome;p.Documentos.Add(new DocumentoCPF(strCPF));p.Endereco.Localidade = localidade;session.SaveOrUpdate(p);
Isso Ao invés disso
Perguntas
Contacte o autor, se preferir ...●http://www.linkedin.com/in/hcmarchezi●http://hcmarchezi.blogspot.com.br/