Return data from a Linq query to an EF Core repository

Asked

Viewed 402 times

2

I have the Person class that relates to the Personal and Personal Tables in a one-on-one relationship. In my table Person I have the field Personnature where 0 = Person and 1 = Legal Person.

A person can be physical or legal and who defines this is the Personal Fieldnature. There is a way for me to give a include in the Personal table, only if Personnature is equal to 0 and to give a include in the Personal table only for Personnature is 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();
        }        
}

inserir a descrição da imagem aqui

  • is Entity Framework Core?

2 answers

0

There is no "pretty" way for you to do this, since the Include cannot stand conditions.

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

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

That way you keep working at the bank and get the result you expect.

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

0


With Entity Framework Core there is a possibility to load the relations and/or the collections subsequently, example:

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 even has to filter the elements that could be loaded, but, is not the case in specific.

In your layer 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;     
    }        
}

About performance, if the registration amount is too large can have low performance, then you have to consider all this, maybe a results pagination would be ideal, but, wanted to show the loading feature of the relations after loading some data.

  • It is Virgilio, now I was doubtful... it is a commercial app and will contain many records, because customers, suppliers, carriers, etc, will be "People" and the bank is normalized... The Bad of normalizing and using good practices is not always good, because it would lose performance in my case. There would be a way to improve this not? How the pagination process would look?

  • So in my view your tables are not fully normalized, because 1:1 I would otherwise mount (or even mount), the best way in your case is pagination, could use a plugin for this example: https://www.nuget.org/packages/X.PagedList.Mvc.Core/ @Jalberromano

  • I’m not being able to use the "context" ex: context.Pessoa.Tolist(); I can only access the Dbset... But when I try to use Dbset.Entry(x) dpa error in Entry...

  • Is it right to do so? public Ienumerable<Person> Getalljoin() { var people = Dbset.Tolist(); people.Foreach(x => { if (x.Personnature == 0) { Dbset.Include("Personal physical"); } Else { Dbset.Include("Legal person"); } }); Return people; }

  • @Jalberromano this piece of code is not the same as what I did, so it’s wrong !!! because it’s a list and not just an item... OK! and in the interaction have to take the item and check what kind of person is

  • I tried to change it because context. Person does not work in my Pository.... It replaces with Dbset... Only it still gives error in .Entry.... Says that does not exist...

  • You have to take the context variable @Jalberromano type Repository<Pessoa>what’s inside

  • It worked @Virgilio Novic. Thank you :)

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.