Error returning list with Fluent NHibernate

3

Within the Web.API project, I've created a Get () method which returns a list of objects - IList. This PersonAcess class has a Log list (1: N).

When you execute the Get () method, an exception occurs:

<ExceptionType>System.InvalidOperationException</ExceptionType>
<ExceptionType>NHibernate.LazyInitializationException</ExceptionType>
<ExceptionMessage>Initializing[RemyWebModel.Entidades.PessoaAcesso#1]-failed to lazily initialize a collection of role: RemyWebModel.Entidades.PessoaAcesso.Logs, no session or session was closed</ExceptionMessage>

Get () method:

    [HttpGet]
    public HttpResponseMessage Getall()
    {
        IList<PessoaAcesso> pessoasAcesso;

        using (var session = NHSessionFactoryManager.GetSessionFactory().OpenSession())
        {
            pessoasAcesso = session.QueryOver<PessoaAcesso>().List();
        }

        return Request.CreateResponse(HttpStatusCode.OK, pessoasAcesso, new JsonMediaTypeFormatter());
    }

Class PersonAccess:

public class PessoaAcesso : Pessoa
{
    [DataType(DataType.Text)]
    [Display(Name = "Login de acesso")]
    [RegularExpression(@"[a-zA-Z]{5,15}", ErrorMessage = "Login deve possuir somente letras e conter entre 5 a 15 caractéres!")]
    [Required(ErrorMessage = "O login deve ser preenchido!")]
    public virtual string Login { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Senha de acesso")]
    [MinLength(5)]
    [Required(ErrorMessage = "A senha deve ser informada!")]
    public virtual string Senha { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Cofirme novamente a senha")]
    [MinLength(5)]
    [Compare("Senha", ErrorMessage = "As senhas não conferem!")]
    public virtual string ConfirmarSenha { get; set; }

    [Display(Name = "Acesso Administrador?")]
    public virtual bool Administrador { get; set; }

    [Display(Name = "Acesso liberado?")]
    public virtual bool AcessoLiberado { get; set; }

    [Display(Name = "Perfil")]
    public virtual PermissaoPerfil Perfil { get; set; }

    public virtual IList<Log> Logs { get; set; }

    public PessoaAcesso()
    {
        Logs = new List<Log>();
    }
}

Log Class:

public class Log
{
    public virtual int Id { get; protected set; }

    public virtual PessoaAcesso PessoaAcesso { get; set; }

    [DataType(DataType.DateTime)]
    [Display(Name = "Data/Hora")]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy - hh:mm:ss}")]
    public virtual DateTime DataHora { get; set; }

    [Display(Name = "Ação")]
    public virtual LogAcao Acao { get; set; }

    [DataType(DataType.Text)]
    [Display(Name = "Descrição")]
    [Required(ErrorMessage = "Descrição precisa ser preenchida!")]
    public virtual string Descricao { get; set; }
}

Person MappingAccess:

public class PessoaAcessoMap : SubclassMap<PessoaAcesso>
{
    public PessoaAcessoMap()
    {
        KeyColumn("Id_Pessoa");

        Map(x => x.Login)
            .Not.Nullable()
            .Length(MapLength.TextoCurto);

        Map(x => x.Senha)
            .Not.Nullable()
            .Length(MapLength.Texto);

        Map(x => x.Administrador)
            .Not.Nullable();

        Map(x => x.AcessoLiberado)
            .Not.Nullable();

        References(x => x.Perfil)
            .Column("Id_PermissaoPerfil");

        HasMany(x => x.Logs)
            .KeyColumn("Id_PessoaAcesso")
            .Cascade.All();
    }
}

So I understand I could not load the children "Log" because the session is closed, I just do not understand where I'm going wrong. Why does this error occur?

    
asked by anonymous 31.07.2014 / 14:20

2 answers

0

The problem was in the session block:

using (var session = NHSessionFactoryManager.GetSessionFactory().OpenSession())

In this case, I need to leave the session open so that the result can be delivered completely, in the case of the child logs.

So, I removed using using leaving the session variable open:

public IEnumerable<PessoaAcesso> GetAll()
{
        var session = NHSessionFactoryManager.GetSessionFactory().OpenSession();

        return session
            .CreateCriteria(typeof(PessoaAcesso))
            .List<PessoaAcesso>();
}
    
05.08.2014 / 18:48
0

The error occurs because the json serializer is trying to access the Logs property outside the session.

  • You can manually access the property within the using block to force it to load.

Or

  • Serialize your entity within the using. Thus the entire graph of the PersonAccess entity will be accessed correctly.

Log Size

You were worried about the size of the Log list, right?

  • Or you take the Nhinernate mapping log, or

  • Create a dto class to which you map your entity. And your api delivers this. In the mapping to the dto you ignore the Log property. You can do the mapping manually, or lean on Automapper: link

It is a good practice to isolate your domain entities from the outside world by returning one that best fits the api requirement.

    
01.08.2014 / 10:56