How to mount a lambda expression and pass it by parameter to a generic function?

2

I need to pass two parameters to a generic function that returns data from the database and select only a few specific columns to display in a DataGridView .

public List<TEntity> GetAll(Expression<Func<TEntity, bool>> Predicate, 
                            Expression<Func<TEntity, TEntity>> Select)
{
       var query = Context.Set<TEntity>()
          .Where(Predicate)
          .Select(Select).ToList();
       return query;
}

For the query that I will perform, I do not need to pass Predicate , I just need to pass Select to return it:

PessoaId, 
Login, 
Senha,  
UsuarioTipoId, 
Descricao(UsuarioTipo), 
PessoaTipoId, 
Descricao(PessoaTipo). 

If the User is an individual, display the fields:

NomeCompleto, 
Apelido,
DataNascimento

but if it is a legal entity, display the fields:

RazaoSocial, 
NomeFantasia,
DataAbertura

It's a rather complex expression. Is it possible to do it and how to pass it by parameter?

Below are the classes:

//CLASSES MODEL
public class PessoaModel
    {
        public int PessoaId { get; set; }
        public int PessoaTipoId { get; set; }
        public DateTime DataInclusao { get; set; }

        public virtual PessoaTipoModel PessoaTipo { get; set; }
        public virtual PessoaFisicaModel PessoaFisica { get; set; }
        public virtual PessoaJuridicaModel PessoaJuridica { get; set; }
    }

 public class UsuarioModel : PessoaModel
 {
        public string Login { get; set; }
        public string Senha { get; set; }
        public int UsuarioTipoId { get; set; }

        public virtual UsuarioTipoModel UsuarioTipo { get; set; }

  }

 public class PessoaFisicaModel
 {
        public int PessoaId { get; set; }
        public string NomeCompleto { get; set; }
        public string Apelido { get; set; }
        public DateTime? DataNascimento { get; set; }
        public string CPF { get; set; }

        public virtual PessoaModel Pessoa { get; set; }
 }

 public class PessoaJuridicaModel
 {
        public int PessoaId { get; set; }
        public string RazaoSocial { get; set; }
        public string NomeFantasia { get; set; }
        public DateTime? DataAbertura { get; set; }
        public string CNPJ { get; set; }

        public virtual PessoaModel Pessoa { get; set; }
 }


 //CARREGAMENTO DO DATAGRIDVIEW
 UsuarioRepository UsuarioRepositorio = new UsuarioRepository();
 dgUsuarios.DataSource = UsuarioRepositorio.GetAll();

I needed something like this (Passing Parameters):

dgPesquisar.DataSource = UsuarioRepositorio.GetAll(null, u => u.login,  u.Senha, u.NOmeCompleto );
    
asked by anonymous 07.11.2016 / 09:27

3 answers

2

Do you want to do it in a simple, flexible or complicated way?

using (var context = new MyWonderfulRepositoryContext())
{
    dgUsuarios.DataSource = 
        from pessoa in context.Pessoas
        where /* minha condicao */
        select new PessoaFisicaModel {
            /* monte o seu objecto aqui */
        }
}

But I want to implement Repository Pattern because someone said it's a good idea ... DbSet<T> already does it, and much better than you ...

What about Unit of Work ? DbContext also already implements this face.

Ah, but I do not like Entity Framework and I will sabotage the project to change ORM to NHibernate in 6 months.

In this case, create a class library with static classes that extend DbContext :

public static PessoasContextExtensions
{
    public static IEnumerable<PessoaFisicaModel> GetPessoasFisicas(this MyWonderfulRepositoryContext context)
    {
        return from pessoa in context.Pessoas
            where /* minha condicao */
            select new PessoaFisicaModel {
                /* monte o seu objecto aqui */
            };
    }
}

And in your application do so.:

dgUsuarios.DataSource = context.GetPessoasFisicas();

And in 6 months, you'll change the subscription of your extensions to GetPessoasFisicas(this MyWonderfulSession session) .

    
07.11.2016 / 14:12
0

Look, as I understand it, GetAll will return all correct people, physical or legal, and what changes are the fields depending on the type?

In this case, the days out that seems correct is in the Person class to have this method abastrate, and implement it in the classes that inherit it. More or less like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestePessoa
{
    public abstract class Pessoa
    {
        public int PessoaId { get; set; }
        public int PessoaTipoId { get; set; }
        public DateTime DataInclusao { get; set; }

        public abstract List<Pessoa> GetAll(Pessoa filtro);
    }
}

And the classes that implement it

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestePessoa
{
    public class PessoaFisica : Pessoa
    {
        public string NomeCompleto { get; set; }
        public string Apelido { get; set; }
        public DateTime? DataNascimento { get; set; }
        public string CPF { get; set; }

        public override List<Pessoa> GetAll(Pessoa filtro)
        {
            var filtroPEssoaFisica = filtro as PessoaFisica;
            var retorno = new List<Pessoa>();

            //faça sua busca aqui e popule retorno com PessoaFisica fazendo cast para Pessoa


            return retorno;
        }
    }
}

And also:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestePessoa
{
    public class PessoaJuridica : Pessoa
    {
        public string RazaoSocial { get; set; }
        public string NomeFantasia { get; set; }
        public DateTime? DataAbertura { get; set; }
        public string CNPJ { get; set; }


        public override List<Pessoa> GetAll(Pessoa filtro)
        {
            var filtroPessoaJur = filtro as PessoaJuridica;
            var retorno = new List<Pessoa>();

            //faça sua busca aqui e popule retorno com PessoaJuridica fazendo cast para Pessoa


            return retorno;
        }
    }
}

Another way, would be to use a life delegate, link

    
07.11.2016 / 14:31
0

Hello,

I have prepared an example of a generic method for you to use as you requested (or asked if it was possible, c # is possible = D)

Generic method:

public IEnumerable<TEntity> Listar<TEntity>(
        Expression<Func<TEntity, bool>> condicao, 
        Expression<Func<TEntity, TEntity>> campos) where TEntity : class
    {
        /*Verifica se possui condição*/
        IQueryable<TEntity> query = condicao != null ? 
                        _bd.Set<TEntity>().Where(condicao) : 
                        _bd.Set<TEntity>();

        /*Verifica se possui campos fitrados*/
        var result = campos != null ? 
                    query.Select(campos).ToList() : 
                    query.ToList();

        return result;
    }

Call for generic method:

public IEnumerable<PessoaFisicaModel> RecuperarPessoasFisicas()
    {
        /*Aqui ele vai buscar todas as pessoas físicas sem a condição where informada*/
        var todasPessoasFisicas = 
            Listar<PessoaFisicaModel>(null, s => new PessoaFisicaModel { PessoaId = s.PessoaId, NomeCompleto = s.NomeCompleto });

        /*Aqui ele vai buscar todas as pessoas que começam com a letra L*/
        var pessoasComLetraL = 
            Listar<PessoaFisicaModel>(
                    w => w.NomeCompleto.StartWith("L"), 
                    s => new PessoaFisicaModel { PessoaId = s.PessoaId, NomeCompleto = s.NomeCompleto });
    }
    
23.11.2016 / 20:41