Hola a todos!

Les presento mi problema que debe ser muy parecido a otros problemas de 
serializacion como el en caso de serializar JSON. En mi caso, tengo el 
problema de que tengo que realizar una exportación de una lista de 
entidades a XML y cuando quiero realizarla tuve que hacer un par de 
*walkarounds* para poder realizar algo cercano sin tener que caer en los 
DTOs ya que, a futuro, voy a estar duplicando todo el dominio para poder 
serializar.

*Historia:*

De primera, intente serializar a XML de una pero me tope con que no se 
puede serializar interfaces. Entonces, investigando un poco caí en este 
tema de StackOverflow donde aparece el primer walkaround: Xml 
Deserialization with Proxy 
<http://stackoverflow.com/questions/14225568/xml-deserialization-with-proxy>
Implemente el walkaround pero me siguió molestando con una 
ProxyAccesException donde me dice, en resumen, que no puede convertir un 
PersistentBag a List<T>. Eso me lo tira en el repositorio genérico para NH 
que tengo incluido aca..
Mirando el mapping no encontré en ningún lado que haya mapeado un List<T>, 
ademas, NH no te lo permite realizar. Entonces, mirando en profundidad, 
únicas propiedades que retornan un List<T> son las la que surrogan las 
listas cuando se serializa a XML.
El tema acá es que no están mapeadas esas listas, por ende, el mapping 
debería ignorar estas propiedades. Y lo peor de todo, es que la excepción 
que me tira es a causa de esto.
Entonces, busque una manera de que ignore a mano las propiedades pero nada 
(Ignoring 
methods on entity types with nHibernate 
<http://stackoverflow.com/questions/1120574/ignoring-methods-on-entity-types-with-nhibernate>
).

Sigo leyendo otras cosas por las cuales puede resolver y "deshabilite" el 
lazyload de la entidad y los de los bags. También encontré una magia para 
desproxificar las entidades (Hacking lazy loaded inheritance 
<http://sessionfactory.blogspot.com.ar/2010/08/hacking-lazy-loaded-inheritance.html>
 y WCF + NHibernate: Entity Serialization 
<http://nhibernate.info/doc/howto/various/wcf-nhibernate-entity-serialization.html>)
 
pero nada...

Acá les dejo el código necesario para que puedan ver donde puede haber una 
solución para esto. Si necesitan revisar mas en profundidad, les dejo el 
repositorio de github: escuela-simple 
<https://github.com/drielnox/escuela-simple>

*Entidad:*

namespace EscuelaSimple.Modelos
{
    [Serializable()]
    public class Personal : IEntidad<uint>
    {
        [XmlAttribute]
        public virtual uint Identificador { get; set; }
        public virtual string Nombre { get; set; }
        public virtual string Apellido { get; set; }
        public virtual uint DNI { get; set; }
        public virtual DateTime FechaNacimiento { get; set; }
        public virtual string Domicilio { get; set; }
        public virtual string Localidad { get; set; }
        [XmlIgnore]
        public virtual ICollection<Telefono> Telefonos { get; protected set; }
        [XmlElementAttribute(IsNullable = true)]
        public virtual DateTime? IngresoDocencia { get; set; }
        [XmlElementAttribute(IsNullable = true)]
        public virtual DateTime? IngresoEstablecimiento { get; set; }
        public virtual string Titulo { get; set; }
        public virtual string Cargo { get; set; }
        public virtual string SituacionRevista { get; set; }
        public virtual string Observacion { get; set; }
        [XmlIgnore]
        public virtual ICollection<Inasistencia> Inasistencias { get; protected 
set; }
 
        public Personal()
        {
            this.Telefonos = new List<Telefono>();
            this.Inasistencias = new List<Inasistencia>();
        }
 
        public void AgregarTelefono(Telefono telefono)
        {
            if (!this.Telefonos.Contains(telefono))
            {
                this.Telefonos.Add(telefono);
            }
        }
 
        public void QuitarTelefono(Telefono telefono)
        {
            if (this.Telefonos.Contains(telefono))
            {
                this.Telefonos.Remove(telefono);
            }
        }
 
        public void AgregarInasistencia(Inasistencia inasistencia)
        {
            if (!this.Inasistencias.Contains(inasistencia))
            {
                this.Inasistencias.Add(inasistencia);
            }
        }
 
        public void QuitarInasistencia(Inasistencia inasistencia)
        {
            if (this.Inasistencias.Contains(inasistencia))
            {
                this.Inasistencias.Remove(inasistencia);
            }
        }
 
        #region Surrogacion para XMLSerializer
 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [XmlArray(ElementName = "Telefonos"), XmlArrayItem("Telefono", 
typeof(Telefono))]
        public virtual List<Telefono> ListaDeTelefonosSurrogado
        {
            get
            {
                List<Telefono> proxy = this.Telefonos as List<Telefono>;
                if (proxy == null && this.Telefonos != null)
                {
                    proxy = (List<Telefono>)this.Telefonos;
                }
 
                return proxy;
            }
            set
            {
                this.Telefonos = value;
            }
        }
 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        [XmlArray(ElementName = "Inasistencias"), XmlArrayItem("Inasistencia", 
typeof(Inasistencia))]
        public virtual List<Inasistencia> ListaDeInasistenciasSurrogada
        {
            get
            {
                List<Inasistencia> proxy = this.Inasistencias as 
List<Inasistencia>;
                if (proxy == null && this.Inasistencias != null)
                {
                    proxy = (List<Inasistencia>)this.Inasistencias;
                }
 
                return proxy;
            }
            set
            {
                this.Inasistencias = value;
            }
        }
 
        #endregion
 
        #region Sobrecarga a Object
 
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
 
            Personal personal = obj as Personal;
            if (personal == null)
            {
                return false;
            }
 
            return this.Identificador.Equals(personal.Identificador) &&
                this.Nombre.Equals(personal.Nombre) &&
                this.Apellido.Equals(personal.Apellido) &&
                this.DNI.Equals(personal.DNI) &&
                this.FechaNacimiento.Equals(personal.FechaNacimiento);
        }
 
        public override int GetHashCode()
        {
            string hashCode = this.Identificador + "|" + this.Nombre + "|" + 
this.Apellido + "|" +
                this.DNI + "|" + this.FechaNacimiento + "|" + this.Domicilio + 
"|" +
                this.Localidad + "|" + this.Telefonos + "|" + 
this.IngresoDocencia + "|" +
                this.IngresoEstablecimiento + "|" + this.Titulo + "|" + 
this.Cargo + "|" +
                this.SituacionRevista + "|" + this.Observacion + "|" + 
this.Inasistencias;
            return hashCode.GetHashCode();
        }
 
        #endregion
    }
}


Mapping:

namespace EscuelaSimple.Datos.Mapeo.NHibernate
{
    public class PersonalMap : ClassMapping<Personal>
    {
        public PersonalMap()
        {
            Lazy(false);
 
            Table("Personal");
 
            Id<uint>(x => x.Identificador, m =>
            {
                m.Access(Accessor.Property);
                m.Column("IdPersonal");
                m.Generator(Generators.Identity);
            });
 
            Property<string>(x => x.Nombre, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Nombre");
                m.NotNullable(true);
            });
            Property<string>(x => x.Apellido, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Apellido");
                m.NotNullable(true);
            });
            Property<uint>(x => x.DNI, m =>
            {
                m.Access(Accessor.Property);
                m.Column("DNI");
                m.UniqueKey("UK_Personal_DNI");
                m.NotNullable(true);
            });
            Property<DateTime>(x => x.FechaNacimiento, m =>
            {
                m.Access(Accessor.Property);
                m.Column("FechaNacimiento");
                m.NotNullable(true);
                m.Type<DateType>();
            });
            Property<string>(x => x.Domicilio, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Domicilio");
                m.NotNullable(false);
            });
            Property<string>(x => x.Localidad, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Localidad");
                m.NotNullable(false);
            });
            Property<DateTime?>(x => x.IngresoDocencia, m =>
            {
                m.Access(Accessor.Property);
                m.Column("IngresoDocencia");
                m.NotNullable(false);
                m.Type<DateType>();
            });
            Property<DateTime?>(x => x.IngresoEstablecimiento, m =>
            {
                m.Access(Accessor.Property);
                m.Column("IngresoEstablecimiento");
                m.NotNullable(false);
                m.Type<DateType>();
            });
            Property<string>(x => x.Titulo, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Titulo");
                m.NotNullable(false);
            });
            Property<string>(x => x.Cargo, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Cargo");
                m.NotNullable(false);
            });
            Property<string>(x => x.SituacionRevista, m =>
            {
                m.Access(Accessor.Property);
                m.Column("SituacionRevista");
                m.NotNullable(false);
            });
            Property<string>(x => x.Observacion, m =>
            {
                m.Access(Accessor.Property);
                m.Column("Observacion");
                m.NotNullable(false);
            });
 
            Set<Telefono>(x => x.Telefonos,
                cm =>
                {
                    cm.Access(Accessor.Property);
                    cm.Table("Telefono");
                    cm.Key(k =>
                    {
                        k.Column(c =>
                        {
                            c.Name("IdPersonal");
                            c.NotNullable(true);
                            c.UniqueKey("UK_Telefono_2");
                        });
                        k.ForeignKey("FK_Telefono_Personal_1");
                        k.NotNullable(true);
                    });
                    cm.Cascade(Cascade.All);
                    cm.Lazy(CollectionLazy.NoLazy);
                },
                m =>
                {
                    m.OneToMany(x =>
                    {
                        x.Class(typeof(Telefono));
                        x.NotFound(NotFoundMode.Exception);
                    });
                });
            Set<Inasistencia>(x => x.Inasistencias,
                cm =>
                {
                    cm.Access(Accessor.Property);
                    cm.Table("Inasistencia");
                    cm.Key(k =>
                    {
                        k.Column(c =>
                        {
                            c.Name("IdPersonal");
                            c.NotNullable(true);
                        });
                        k.ForeignKey("FK_Inasistencia_Personal_1");
                        k.NotNullable(true);
                    });
                    cm.Cascade(Cascade.All);
                    cm.Lazy(CollectionLazy.NoLazy);
                },
                m =>
                {
                    m.OneToMany(x =>
                    {
                        x.Class(typeof(Inasistencia));
                        x.NotFound(NotFoundMode.Exception);
                    });
                });
        }
    }
}


*Repositorio generico para NH:*

namespace EscuelaSimple.Datos.Repositorio
{
    public abstract class NHibernateRepositorio<TEntidad, TClavePrimaria> : 
IRepositorio<TEntidad, TClavePrimaria>
        where TEntidad : class, IEntidad<TClavePrimaria>
        where TClavePrimaria : struct
    {
        public ISession Sesion { get; set; }
 
        public NHibernateRepositorio(ISession sesion)
        {
            this.Sesion = sesion;
        }
 
        public TEntidad ObtenerPorIdentificador(TClavePrimaria id)
        {
            return this.Sesion.Get<TEntidad>(id);
        }
 
        public IEnumerable<TEntidad> ObtenerTodo()
        {
            IQueryOver<TEntidad> result = this.Sesion.QueryOver<TEntidad>();
            return result.List(); // <<< Aca tira ProxyAccessException!!!
        }
 
        public void Crear(TEntidad entity)
        {
            this.Sesion.Save(entity);
        }
 
        public void Actualizar(TEntidad entity)
        {
            this.Sesion.Update(entity);
        }
 
        public void Borrar(TEntidad entity)
        {
            this.Sesion.Delete(entity);
        }
 
        public TEntidad ObtenerPor(Predicate<TEntidad> predicate)
        {
            List<TEntidad> result = this.FiltrarPor(predicate) as 
List<TEntidad>;
            return result.Count > 0 ? result[0] : null;
        }
 
        public IEnumerable<TEntidad> FiltrarPor(Predicate<TEntidad> predicate)
        {
            List<TEntidad> result = this.ObtenerTodo() as List<TEntidad>;
            return result.FindAll(predicate);
        }
    }
}







-- 
-- 
Para escribir al Grupo, hágalo a esta dirección: 
NHibernate-Hispano@googlegroups.com
Para más, visite: http://groups.google.com/group/NHibernate-Hispano
--- 
Has recibido este mensaje porque estás suscrito al grupo "NHibernate-Hispano" 
de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía 
un correo electrónico a nhibernate-hispano+unsubscr...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/d/optout.

Responder a