Pregunta

Tengo que mapear dos tablas simples con una relación de clave externa. Una de las tablas es Contacto que contiene las columnas id (clave principal de tipo int), nombre , dirección y < strong> guid (recién agregado y no es la clave principal). El otro es número de teléfono que contiene las columnas id (clave principal de tipo int), contact___id (clave externa de id en la tabla de contactos) y phone__number .

El archivo de mapeo para la tabla de contacto es el siguiente:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="Contact" table="Contact">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>

    <property name="Name" column="name" type="string"/>
    <property name="Address" column="address" type="string"/>
    <property name="Guid" column="guid" type="string"/>

    <set lazy="true" batch-size="6" table="phone_number" name="PhoneNumbers" fetch="join" inverse="false" cascade="all" >
      <key foreign-key="FK_contact_phone_number" column="contact_id"/>
      <one-to-many class="PhoneNumber" />
    </set>

  </class>
</hibernate-mapping>

El archivo de mapeo para la tabla Phone_number es:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="PhoneNumber" table="phone_number">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="ContactId" column="contact_id" />
    <property name="Number" column="phone_number" />
  </class>
</hibernate-mapping>

Las clases Contact y PhoneNumber son:

namespace OfflineDbSyncWithNHibernate.Models
{
    public class Contact
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string Address { get; set; }
        public virtual string Guid { get; set; }
        public virtual PhoneNumbers PhoneNumbers { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumber
    {
        public virtual int Id { get; set; }
        public virtual int ContactId { get; set; }
        public virtual string Number { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumbers : List<PhoneNumber>
    {
    }
}

Cuando cargo el contacto y los números de teléfono por separado, funciona, pero después de agregar el elemento establecido para obtener una relación uno a muchos, nhibernate está dando un error:

NHibernate.MappingException: información de asignación no válida especificada para el tipo OfflineDbSyncWithNHibernate.Models.Contact, verifique que el archivo de asignación no coincida con el tipo de propiedad

Soy nuevo en nHibernate, así que no estoy seguro de si hay un error en el elemento set o si ni siquiera debería estar usándolo. Cualquier ayuda será apreciada.

¿Fue útil?

Solución

Solo recuerda esto

  • La bolsa se implementa usando IList
  • El conjunto se implementa usando ISet
  • La lista se implementa usando ArrayList o List
  • El mapa se implementa utilizando HashedTable o IDictionary

Si desea usar IList, use la primera regla, es decir, cambie su hbm.xml para usar Bag en lugar de Set, su clase Phonenumbers debe heredar de IList no List, si desea usar List necesitará cambiar su archivo de mapeo a use List en lugar de Set.

Otros consejos

Creo que su clase PhoneNumbers necesita heredar de un subtipo de Iesi.Collections.ISet. No creo que haya un & Quot; Set & Quot; tipo proporcionado en .NET por defecto. Ver hibernate Preguntas frecuentes

  

El < set > mapas a un   Iesi.Collections.ISet. Esa interfaz   es parte de Iesi.Collections   ensamblado distribuido con NHibernate.

Su tipo de colección debe ser una interfaz, porque NHibernate proporcionará su propio tipo que implementa esa interfaz cuando se recupera un objeto de la base de datos.

Si define su colección como

public virtual ISet<PhoneNumber> Phonenumbers = new HashedSet<Phonenumber>();

Entonces creo que funcionará.

Para controlar mejor el acceso a su colección, puede modificar su clase de contacto de esta manera:

public class Contact
{
    public virtual int Id {get;set;}
    ..

    private ISet<Phonenumber> _phoneNumbers = new HashedSet<PhoneNumber>();

    public ReadOnlyCollection<Phonenumber> PhoneNumbers
    {
        get 
        {
           return new List<Phonenumber>(_phoneNumbers).AsReadOnly();
        }
    }

    public void AddPhonenumber( Phonenumber n )  
    {
        n.Contact = this;
        _phoneNumbers.Add(n);
    }

    public void RemovePhoneNumber( PhoneNumber n )
    {
        ...
    }
}

Luego, debe asegurarse de que en su asignación de la clase Contact, especifique que NHibernate debe acceder al campo _phoneNumbers en lugar de la propiedad PhoneNumber:

<set name="PhoneNumbers" access="field.camelcase-underscore" ... >
   ...
</set>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top