18

Tengo las siguientes tablas en mi base de datos:Compuesto Tecla/Id con NHibernate

Announcements: 
- AnnouncementID (PK) 
- Title 

AnouncementsRead (composite PK on AnnouncementID and UserID): 
- AnnouncementID (PK) 
- UserID (PK) 
- DateRead 

Users: 
- UserID (PK) 
- UserName 

Por lo general, me gustaría en el mapa los "AnnouncementsRead" por medio de una relación de muchos a muchos, pero esta tabla también tiene un adicional Campo "DateRead".

Hasta ahora he definido las siguientes entidades:

public class Announcement 
    { 
     public virtual int AnnouncementID { get; set; } 
     public virtual string Title { get; set; } 
     public virtual IList<AnnouncementRead> AnnouncementsRead { get; private set; } 

     public Announcement() 
     { 
      AnnouncementsRead = new List<AnnouncementRead>(); 
     } 
    } 

    public class AnnouncementRead 
    { 
     public virtual Announcement Announcement { get; set; } 
     public virtual User User { get; set; } 
     public virtual DateTime DateRead { get; set; } 
    } 

    public class User 
    { 
     public virtual int UserID { get; set; } 
     public virtual string UserName { get; set; } 
     public virtual IList<AnnouncementRead> AnnouncementsRead { get; private set; } 

     public User() 
     { 
      AnnouncementsRead = new List<AnnouncementRead>(); 
     } 
} 

Con las siguientes asignaciones:

public class AnnouncementMap : ClassMap<Announcement> 
{ 
    public AnnouncementMap() 
    { 
     Table("Announcements"); 
     Id(x => x.AnnouncementID); 
     Map(x => x.Title); 
     HasMany(x => x.AnnouncementsRead) 
      .Cascade.All(); 
    } 
} 

public class AnnouncementReadMap : ClassMap<AnnouncementRead> 
{ 
    public AnnouncementReadMap() 
    { 
     Table("AnnouncementsRead"); 
     CompositeId() 
      .KeyReference(x => x.Announcement, "AnnouncementID") 
      .KeyReference(x => x.User, "UserID"); 
     Map(x => x.DateRead); 
    } 
} 

public class UserMap : ClassMap<User> 
{ 
    public UserMap() 
    { 
     Table("Users"); 
     Id(x => x.UserID); 
     Map(x => x.UserName); 
     HasMany(x => x.AnnouncementsRead) 
      .Cascade.All(); 
    } 
} 

Sin embargo cuando corro este recibo el siguiente error:

"composite-id class must override Equals(): Entities.AnnouncementRead" 

Apreciaría que alguien pudiera señalarme en la dirección correcta. Gracias

Respuesta

7

Debe hacer exactamente lo que NHiberante le está diciendo. AnnouncementRead debe anular los métodos Equals y GetHashCode. Ellos deben basarse en los campos que forman parte de la clave primaria

0
  1. Al implementar es igual que debe uso instanceof para permitir la comparación con las subclases. Si Hibernate perezosa carga una relación uno a uno o muchos a uno, tendrá un proxy para la clase en lugar de la clase simple. Un proxy es una subclase. Comparar los nombres de clase fallaría.
    Más técnicamente: Debe seguir el Principio de sustitución de Liskows e ignorar la simétrica.
  2. El siguiente inconveniente es utilizar algo como name.equals (that.name) en lugar de name.equals (that.getName()). El primero fallará, si eso es un proxy.

http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html

+0

La pregunta se refiere a C# y NHibernate, no Hibernate y Java. No hay tal cosa 'instanceof', no hay problema como '.name'-vs-'.getName'. Si bien, en general, su respuesta es correcta y una persona experimentada tanto en C# como en Java puede "transferir los conceptos" a través del límite del lenguaje/plataforma. Sin embargo, no hay muchas personas así, y eso hace que tu respuesta apenas sea utilizable. – quetzalcoatl