none
GetHashCode Equals X Nhibernate RRS feed

  • Pergunta

  • Pessoal estou com uma dúvida em relação a utilização do nhibernate para mapeamento OR, encontrei em vários blogs(em inglês) sobre o fato de ter que fazer override nos métodos gethashcode e equals nas classes persistentes(tabelas) com chave composta, mas eu como utilizador VIP do google translate para textos em inglês, não obtive sucesso em entender o real motivo dessa rotina de override...

    a um tempo atrás descobri na prática que só deve sobrescrever realmente o gethashcode se e somente se a classe tiver chave composta, se não dá outro tipo de erro também, 

    aqui a na empresa onde trabalho nós estamos desenvolvendo um software em c# que utiliza não só nhibernate como também o spring e o que me deixa mais confuso é que nesses overrides nós simplesmente sobrescrevemos com o retorno base.gethashcode... ex.:

    public override int GetHashCode()
            {
                return base.GetHashCode();
            }

    não sei se é correto assim pois a pessoa que fez essas rotinas já não se encontra mais na empresa e ninguém soube me dizer o motivo disso(tá funcionando é o que importa eles dizem ¬¬')...

    aguardo resposta...

    abraço!

    quinta-feira, 14 de junho de 2012 11:21

Respostas

  • MaiconLL,

    O NHibernate precisa que seja implementado o GetEquals e o Equals, para poder comparar os seus objetos.

    Através desses métodos você diz ao NHibernate quando um objeto é igual a outro. Ele usa isso para gerenciar a session de objetos que ele possui. Ele precisa saber isso para realizar várias operações com os objetos.

    Se ainda tiver dúvida, é só falar.


    Alexsandre Rodrigues de Almeida - MCTS .NET Framework - Web Applications
    E-mail: alexsandrer@gmail.com
    Twitter: @AlexRAlmeida

    • Marcado como Resposta M a i c o n terça-feira, 24 de julho de 2012 13:30
    terça-feira, 17 de julho de 2012 15:30
  • Maicon esse override do metodo GetHashCode nao faz sentido nenhum e nao vai fazer diferenca nenhuma pois esta executando exatamente o mesmo metodo que foi sobrescrito.

    Quanto ao NHibernate precisar que voce sobrescreva esse metodos em caso de chave composta é porque ele vai utilizar esse metodo para identificar a chave de sua tabela, fazer o where com esse dado no caso de operacoes CRUD

    Espero ter ajudado.

    terça-feira, 17 de julho de 2012 21:04
  • A resposta do Colega Anselmo responde bem a questão. 

    Quando você faz o override destes métodos, você deverá ensinar ao compilador como fazer para comparar o objeto da sua classe com outro objeto, pois uma comparação simples entres dois complexos será sempre False.

    A forma como você implementou não está errada, mas por exemplo, se você precisar fazer um DISTINCT ou um GROUP BY através do nHibernate, provavelmente você irá se deparar com algum comportamento estranho. 

    veja um este exemplo, eu tenho uma entidade que representa uma tabela de intersecção para um relacionamento N:N então está entidade não tem uma chave primária própria mas uma chave composta(compositeID) formada entre as chaves das entidades que se relacionam através dela.

        public class GrupoTipoUsuario
        {
            /// <summary>
            /// Tipo de Usuário
            /// </summary>
            public virtual TipoUsuario Tipo { get; set; }
    
            /// <summary>
            /// Grupo de Usuário
            /// </summary>
            public virtual GrupoUsuario Grupo { get; set; }
    
            /// <summary>
            /// Data de Criação da entidade
            /// </summary>
            public virtual DateTime DataInclusaoRegistro { get; set; }
    
            /// <summary>
            /// Data de Deleção da entidade
            /// </summary>
            public virtual DateTime? DataDelecaoRegistro { get; set; }
    
            /// <summary>
            /// Usuário que criou a entidade
            /// </summary>
            public virtual Usuario UsuarioCriador { get; set; }
    
            /// <summary>
            /// Override do método Equals
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <param name="obj">Objeto p/ comparação</param>
            /// <returns>Retorno da comparação</returns>
            public override bool Equals(object obj)
            {
                GrupoTipoUsuario lobjGTU = new GrupoTipoUsuario();
    
                return ((Tipo.Sequencial.Equals(lobjGTU.Tipo.Sequencial)) && (Grupo.Sequencial.Equals(lobjGTU.Grupo.Sequencial)));
            }
    
            /// <summary>
            /// Override do método GetHashCode
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <returns></returns>
            public override int GetHashCode()
            {
                return Tipo.Sequencial.GetHashCode() + Grupo.Sequencial.GetHashCode();
            }
        }


    Olavo Oliveira Neto
    http://olavooneto.wordpress.com
    Twitter @Olavooneto
    Facebook Olavo Neto
    Linkedin Olavo Neto
    Se for útil marque como resposta e faça um Developer feliz :)

    • Marcado como Resposta M a i c o n terça-feira, 24 de julho de 2012 13:30
    quarta-feira, 18 de julho de 2012 11:16
    Moderador

Todas as Respostas

  • MaiconLL,

    O NHibernate precisa que seja implementado o GetEquals e o Equals, para poder comparar os seus objetos.

    Através desses métodos você diz ao NHibernate quando um objeto é igual a outro. Ele usa isso para gerenciar a session de objetos que ele possui. Ele precisa saber isso para realizar várias operações com os objetos.

    Se ainda tiver dúvida, é só falar.


    Alexsandre Rodrigues de Almeida - MCTS .NET Framework - Web Applications
    E-mail: alexsandrer@gmail.com
    Twitter: @AlexRAlmeida

    • Marcado como Resposta M a i c o n terça-feira, 24 de julho de 2012 13:30
    terça-feira, 17 de julho de 2012 15:30
  • Maicon esse override do metodo GetHashCode nao faz sentido nenhum e nao vai fazer diferenca nenhuma pois esta executando exatamente o mesmo metodo que foi sobrescrito.

    Quanto ao NHibernate precisar que voce sobrescreva esse metodos em caso de chave composta é porque ele vai utilizar esse metodo para identificar a chave de sua tabela, fazer o where com esse dado no caso de operacoes CRUD

    Espero ter ajudado.

    terça-feira, 17 de julho de 2012 21:04
  • A resposta do Colega Anselmo responde bem a questão. 

    Quando você faz o override destes métodos, você deverá ensinar ao compilador como fazer para comparar o objeto da sua classe com outro objeto, pois uma comparação simples entres dois complexos será sempre False.

    A forma como você implementou não está errada, mas por exemplo, se você precisar fazer um DISTINCT ou um GROUP BY através do nHibernate, provavelmente você irá se deparar com algum comportamento estranho. 

    veja um este exemplo, eu tenho uma entidade que representa uma tabela de intersecção para um relacionamento N:N então está entidade não tem uma chave primária própria mas uma chave composta(compositeID) formada entre as chaves das entidades que se relacionam através dela.

        public class GrupoTipoUsuario
        {
            /// <summary>
            /// Tipo de Usuário
            /// </summary>
            public virtual TipoUsuario Tipo { get; set; }
    
            /// <summary>
            /// Grupo de Usuário
            /// </summary>
            public virtual GrupoUsuario Grupo { get; set; }
    
            /// <summary>
            /// Data de Criação da entidade
            /// </summary>
            public virtual DateTime DataInclusaoRegistro { get; set; }
    
            /// <summary>
            /// Data de Deleção da entidade
            /// </summary>
            public virtual DateTime? DataDelecaoRegistro { get; set; }
    
            /// <summary>
            /// Usuário que criou a entidade
            /// </summary>
            public virtual Usuario UsuarioCriador { get; set; }
    
            /// <summary>
            /// Override do método Equals
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <param name="obj">Objeto p/ comparação</param>
            /// <returns>Retorno da comparação</returns>
            public override bool Equals(object obj)
            {
                GrupoTipoUsuario lobjGTU = new GrupoTipoUsuario();
    
                return ((Tipo.Sequencial.Equals(lobjGTU.Tipo.Sequencial)) && (Grupo.Sequencial.Equals(lobjGTU.Grupo.Sequencial)));
            }
    
            /// <summary>
            /// Override do método GetHashCode
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <returns></returns>
            public override int GetHashCode()
            {
                return Tipo.Sequencial.GetHashCode() + Grupo.Sequencial.GetHashCode();
            }
        }


    Olavo Oliveira Neto
    http://olavooneto.wordpress.com
    Twitter @Olavooneto
    Facebook Olavo Neto
    Linkedin Olavo Neto
    Se for útil marque como resposta e faça um Developer feliz :)

    • Marcado como Resposta M a i c o n terça-feira, 24 de julho de 2012 13:30
    quarta-feira, 18 de julho de 2012 11:16
    Moderador
  • A resposta do Colega Anselmo responde bem a questão. 

    Quando você faz o override destes métodos, você deverá ensinar ao compilador como fazer para comparar o objeto da sua classe com outro objeto, pois uma comparação simples entres dois complexos será sempre False.

    A forma como você implementou não está errada, mas por exemplo, se você precisar fazer um DISTINCT ou um GROUP BY através do nHibernate, provavelmente você irá se deparar com algum comportamento estranho. 

    veja um este exemplo, eu tenho uma entidade que representa uma tabela de intersecção para um relacionamento N:N então está entidade não tem uma chave primária própria mas uma chave composta(compositeID) formada entre as chaves das entidades que se relacionam através dela.

        public class GrupoTipoUsuario
        {
            /// <summary>
            /// Tipo de Usuário
            /// </summary>
            public virtual TipoUsuario Tipo { get; set; }
    
            /// <summary>
            /// Grupo de Usuário
            /// </summary>
            public virtual GrupoUsuario Grupo { get; set; }
    
            /// <summary>
            /// Data de Criação da entidade
            /// </summary>
            public virtual DateTime DataInclusaoRegistro { get; set; }
    
            /// <summary>
            /// Data de Deleção da entidade
            /// </summary>
            public virtual DateTime? DataDelecaoRegistro { get; set; }
    
            /// <summary>
            /// Usuário que criou a entidade
            /// </summary>
            public virtual Usuario UsuarioCriador { get; set; }
    
            /// <summary>
            /// Override do método Equals
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <param name="obj">Objeto p/ comparação</param>
            /// <returns>Retorno da comparação</returns>
            public override bool Equals(object obj)
            {
                GrupoTipoUsuario lobjGTU = new GrupoTipoUsuario();
    
                return ((Tipo.Sequencial.Equals(lobjGTU.Tipo.Sequencial)) && (Grupo.Sequencial.Equals(lobjGTU.Grupo.Sequencial)));
            }
    
            /// <summary>
            /// Override do método GetHashCode
            /// Necessário para o funcionamento do Fluent + NHibernate
            /// </summary>
            /// <returns></returns>
            public override int GetHashCode()
            {
                return Tipo.Sequencial.GetHashCode() + Grupo.Sequencial.GetHashCode();
            }
        }


    Olavo Oliveira Neto
    http://olavooneto.wordpress.com
    Twitter @Olavooneto
    Facebook Olavo Neto
    Linkedin Olavo Neto
    Se for útil marque como resposta e faça um Developer feliz :)

    Olavo Oliveira Neto, e como seria feito um CRUD diretamente nesta entidade, tipo (Create, Read, Update, Delete).

    Estou trabalhando com um relacionamento N x N deste tipo que há dados adicionais na tabela de relacionamento, e algumas consultas devem ser feitas através do relacionamento para acessar estes campos.

    O Create, Update e Delete, já implementei meu grande problema esta sendo o Read, pois tanto os métodos .Get e .Load, pedem em seus parâmetros um id único, que no caso não há nesta entidade. Como seria implementado o método Read(); desta entidade?

    Sei que o post já é velho, mais o meu problemas esta totalmente explicado aqui.

    Aguardo retorno.

    Att. Fernando Leal.


    Fernando

    terça-feira, 29 de janeiro de 2013 13:14