Return data from a query with Linq in an EF Core repository

2

I have the Person class that relates to the PersonPhysical and PersonJuridica tables in a one-to-one relationship. In my Person table I have the Field PersonNature where 0 = Individual and 1 = Legal Entity.

A person can be physical or legal and who defines this is the Field Person Nature. Is there a way for me to give an include in the PersonPicture table, only if PersonNature equal 0 and give an include in PersonJuridic only table of PersonNature equal to 1?

public class PessoaRepository : Repository<Pessoa>, IPessoaRepository
{
        public PessoaRepository(SistemaComercialContext context)
            :base(context)
        {

        }

        public IQueryable<Pessoa> GetAllJoin()
        {
            return DbSet //DbSet Pessoa
                .Include("PessoaFisica")
                .Include("PessoaJuridica")
                .AsNoTracking();
        }        
}
  

    
asked by anonymous 15.02.2018 / 21:05

2 answers

0

With Entity Framework Core there is a possibility to load the and / or relationships later, example strong>:

using (Db db = new Db())
{
    var pessoa = db.Pessoa.Find(1);
    if (pessoa.PessoaNatureza == 0)
    {
        db.Entry(pessoa)
            .Reference(x => x.PessoaFisica)
            .Load(); // Carregando só se for Pessoa Fisica
    }
    else
    {
        db.Entry(pessoa)
            .Reference(x => x.PessoaJuridica)
            .Load(); // Carregando só se for Pessoa Juridica
    }
}

This type of loading is a new feature, which also has filtering elements that could be loaded, but this is not the case.

In your layer you could drive that same code with some changes, example :

public class PessoaRepository : Repository<Pessoa>, IPessoaRepository
{
    public PessoaRepository(SistemaComercialContext context)
        :base(context)
    {

    }

    public List<Pessoa> GetAllJoin()
    {
        var pessoas = context.Pessoa.ToList();
        pessoas.ForEach(x =>
        {                    
            if (x.PessoaNatureza == 0)
            {
                context.Entry(x)
                    .Reference(f => f.PessoaFisica)
                    .Load();
            }
            else
            {
                context.Entry(x)
                    .Reference(j => j.PessoaJuridica)
                    .Load();
            }
        });
        return pessoas;     
    }        
}

On performance, if the registry quantity is too large may have poor performance, then, have to ponder all this, maybe a results pagination would be ideal, but, wanted to show the resource loading relations after loading some data.

    
15.02.2018 / 23:30
0

There is no "pretty" way for you to do this, since Include does not support conditions.

One way is to separate it into two queries and then merge it:

return DbSet.Where(p => p.PessoaNatureza == 0)
            .Include("PessoaFisica")
            .Concat(
                   DbSet.Where(p => p.PessoaNatureza == 1)
                        .Include("PessoaJuridica")
            ).AsNoTracking();

This way you keep your work in the bank and have the result you expect.

There are other ways, using anonymous objects to return the data and then filter in memory. An example this link which also contains a code for a IQueryable extension for this "problem" of Include .

    
15.02.2018 / 22:35