Fluent NHibernate e dúvida nas entidades

99 views
Skip to first unread message

Guilherme Cardoso

unread,
Jun 10, 2010, 8:44:53 PM6/10/10
to NHibernate Portugal
Boas.

Como é o meu primeiro post nesta mailling list vou-me apresentar. Sou
o Guilherme, tenho 19 anos e decidi há poucos dias começar a estudar
NHibernate e fui recomendado pelo colega Ricardo a inscrever-me aqui.
Agora falando de duas dúvidas que tenho.


Pelo que percebi a utilização do Fluent NHibernate é usada para mapear
as entidades através de código e não de arquivos XML.
Pela experiência que têm recomendam-me que comece já a usar Fluent
NHibernate ou vai da escolha de cada um?


Outra questão que tenho é nas entidades. Ao seguir uns artigos de
introdução a NHibernate estava a criar uma entidade e deparei-me com
uma dúvida. No campo Id declarei-a da seguinte forma:
public virtual int Id { get; private; }
O uso do private no Id da entidade é mesmo recomendado? Pelo que
consegui entender, foi dado para que apenas o NHibernate lhe possa
aceder. Mas se eu quiser por exemplo criar um método para actualizar
uma tabela, vou precisar de preencher o campo Id para que a camada de
dados receba e possa actualizar.
Então devo criar a propriedade Id com get; private ou com get; set; ?


Abraços e desde já obrigado!

Ricardo Peres

unread,
Jun 11, 2010, 6:43:06 AM6/11/10
to NHibernate Portugal
Olá, Guilherme!

Por partes! :-)
O motivo para ter uma propriedade apenas de leitura (ou, melhor dito,
com o setter privado) tem a ver com a seguinte pergunta: queremos/
devemos poder modificar o valor dessa propriedade? No caso de valores
gerados pelo servidor (SQL Server IDENTITY, Oracle sequences, campos
calculados, fórmulas, etc), a resposta é normalmente não, pelo que o
campo deve ser privado. Por outro lado, se estivermos a usar
IStatelessSession, que não usa a cache de primeiro nível, podemos
passar uma instância de um objecto, atribuindo-lhe a chave
manualmente, e assim simulamos uma entidade carregada da BD, por
exemplo:

IStatelessSession session = ...;
session.Delete(new MinhaEntidade{ ID = 1 });

Se o setter for privado, não consegues fazer isto, só se usares
reflection.

Quanto ao Fluent NHiberrnate, não sei qual a opinião das outas pessoas
da mailing list, mas eu acho que deverías começar por aprender os
mapeamentos com XML, e depois passar para Fluent.

Abraço,

RP


On Jun 11, 1:44 am, Guilherme Cardoso <guilherme-card...@msn.com>
wrote:

Guilherme Cardoso

unread,
Jun 12, 2010, 11:23:44 AM6/12/10
to NHibernate Portugal
Boas Ricardo,

Obrigado pela ajuda. Estou agora com outra dúvida relacionada com o Id
de cada tabela.

Numa primeira fase já consegui criar um método muito simples para
inserir valores (ainda estou a tentar compreender melhor a
arquitectura para depois separar na camada de dados da de
configuração), mas estou a ter problemas com o Id.

Nos manuais que tenho lido na Net, na parte das entidades declaram o
Id como Guid, mas senão me engano isto gera um numero 128-bit e eu
queria usar a auto-incrementação do SQL Server.
Experimentei mudar o tipo Guid para Int32 nas entidades. O problema
penso que esteja no mapeamento que estou a usar no generator a class
assigned.
Será que no campo Id tenho de fazer uma consulta á base de dados para
ver o último Id inserido, e só depois é que incremento mais um número?

Abraço

Guilherme Cardoso

unread,
Jun 12, 2010, 11:49:19 AM6/12/10
to NHibernate Portugal
Bem, problema resolvido com a class native na id.
Vou agora tentar dividir isto correctamente em camadas ;)

Ricardo Peres

unread,
Jun 12, 2010, 1:04:33 PM6/12/10
to NHibernate Portugal
Guilherme,

Envia o código (simplificado) e o mapeamento, sff.
Parece-me que estás a fazer uma confusão: podes ter chaves Guid
(UNIQUEIDENTIFIER no SQL Server, RAW(16) no Oracle) ou Int32, mas as
colunas e as propriedades têm de bater certo. Se estás a usar o
gerador assigned, isto significa que tens de ser tu a dar o valor, o
que é bastante mais fácil no caso de Guids, basta teres uma
propriedade assim:

private Guid id = Guid.NewGuid();

public Guid Id { get { return (this.id); } private set { } }

Normalmente usarias um Guid, por exemplo, se estiveres a usar a
estratégia de mapeamento de heranças Table Per Concrete Type, se
quiseres, eu explico porquê (tenta descobrir! ;-)).

De qualquer forma, seguramente que não tens de fazer nenhuma consulta
manual à BD para saberes o ID inserido!

Abraço,

RP


On Jun 12, 4:23 pm, Guilherme Cardoso <guilherme-card...@msn.com>
wrote:

Guilherme Cardoso

unread,
Jun 12, 2010, 1:55:07 PM6/12/10
to NHibernate Portugal
Boas Ricardo,

Não sabia disso. Até agora tenho sempre usado os Id como tipo Int32
com auto-incrementação pois pensava que era a única forma de o fazer.
Os códigos estão aqui:
-Contexto: http://codepaste.net/mrnoo5
-Entidade Noticia: http://codepaste.net/tfx92i
-Mapeamento Noticia: http://codepaste.net/2vt1no
-Camada de Acesso de Dados: http://codepaste.net/g1sbzy

Se puderes, diz-me se estou a estruturar bem.

Abraço e obrigado pela paciência ;)

Guilherme Cardoso

unread,
Jun 12, 2010, 2:59:35 PM6/12/10
to NHibernate Portugal
Sobre a utilização do Guid em mapeamentos de herança Table Per
Concerte Type, tem alguma coisa haver com duas tabelas e não haverem
chaves primárias iguais entre elas?
Devo ter dito asneira lol, tirei essa ideia de um artigo que li agora

Ricardo Peres

unread,
Jun 12, 2010, 5:07:41 PM6/12/10
to NHibernate Portugal
Exactamente isso:

class ClasseBase{}
class ClasseDerivada1 : ClasseBase{}
class ClasseDerivada2 : ClasseBase{}

ClasseBase c = session.Get<ClasseBase>(1);

Se existir um 1 em mais do que uma tabela associada à hierarquia
ClasseBase, são devolvidos vários registos, o que não pode acontecer
quando se está a carregar uma entidade pela sua chave.

RP



On Jun 12, 7:59 pm, Guilherme Cardoso <guilherme-card...@msn.com>
wrote:

Ricardo Peres

unread,
Jun 12, 2010, 6:00:14 PM6/12/10
to NHibernate Portugal
Guilherme,

No método Noticias_Adicionar deverias usar SaveOrUpdateCopy em vez de
Save, já que a entidade pertence a outra sessão (ou a nenhuma), e o
NHibernate não tem forma de saber se esta é recém-criada ou está
modificada; está a funcionar porque o valor default de Int32 (unsaved-
value) é 0, o NHibernate olha para a chave e vê que não tem valor,
pelo que assume que a entidade é nova, mas se usasses outro tipo de
chave (Guid), já não deve funcionar.
Atenção que o not-null no mapeamento apenas te garante que, se usares
o NHibernate para gerar a base de dados, ele cria as colunas como NOT
NULL, se é isso que pretendes, define também o tamanho máximo com o
atributo length; tem atenção que este atributo não vai causar
validação da entidade, se tentares gravar valores null, vai estoirar.
Sempre que as colunas têm o mesmo nome das propriedades, sem contar
com maiúsculas, como no teu exemplo, podes omitir o atributo column, o
NHibernate assume que é igual ao name.
Relativamente à forma como estás a gerar o session factory, tudo bem,
assegura-te que só há uma session factory por application. Quanto à
session, é frequente guardá-la no request (HttpContext.Current.Items),
criando-a no BeginRequest e fechando-a no EndRequest (pattern open
session in view).

Abraço,

RP


On Jun 12, 6:55 pm, Guilherme Cardoso <guilherme-card...@msn.com>
wrote:

Guilherme Cardoso

unread,
Jun 12, 2010, 10:42:03 PM6/12/10
to NHibernate Portugal
Outro aspecto que reparei em relação á propriedade not-null nos
mapeamentos era no meu método para apagar noticias.

Da forma que está, para apagar uma noticia eu estou a preencher apenas
o Id dessa noticia. E quando ele tentava apagar a notícia o Titulo e o
Corpo iam vazios e dava-me erro, tive de tirar essa propriedade.

Ricardo Peres

unread,
Jun 13, 2010, 5:10:03 AM6/13/10
to NHibernate Portugal
Isso porque o NHibernate não conhece a tua entidade, não está na cache
de primeiro nível, porque não foi carregada pela entidade corrente.
Como te disse num mail anterior, se usasses IStatelessSessions, não
terias esse problema, no teu caso, deverias fazer primeiro um Update
ou um Refresh à entidade que vais apagar (ou, melhor ainda, usar HQL).

RP


On Jun 13, 3:42 am, Guilherme Cardoso <guilherme-card...@msn.com>
wrote:
Reply all
Reply to author
Forward
0 new messages