Filtering PostgreSQL information on Windows Forms using Entity Framework

6

Is there any way to find the information in postgresql by nickname? But without using alias , just in the field record in the table do I already enter the real name for the field?

Example:

  
  • customer_id will be called "Customer Code"
  •   
  • dtNascimento as the name of "Date of Birth"
  •   

    I would like to create a generic class that works for any table, thus putting the field name as the filter. Something like:

    So that each field added in the table in the future can already be used as a filter in a search screen and already with the real name for the user.

    Is there any way to do this? just need some hint than researching that code I'm turning, but I do not know what technology to use or where to start.

        
    asked by anonymous 17.04.2017 / 22:36

    1 answer

    4

    Yes. Use [Column] :

    [Column("Código Cliente")]
    public int ClienteId { get; set; }
    
    [Column("Data de Nascimento")]
    public DateTime DataNascimento { get; set; }
    
      

    The title of the question should be "How to filter in Winforms by the name of the displayed column". I made a simulation and soon I must edit this answer and put the example in a chapter of Coding Craft because I inadvertently did a tutorial on how to use Entity Framework with Windows Forms and PostgreSQL.

    Let's ask the questions:

      

    Is there any way to find the information in postgresql by nickname? but without using alias, just in the field register in the table do I already enter the real name for the field?

    No. You need to pass the same column name. What you can do is the user interface display the friendly column name and the code receive the column name as it actually is.

      

    I would like to create a generic class that works for any table, thus putting the field name as a filter.

    This involves using a lot Reflection . Using the "field name" is not a good idea, but you can display the field name and get another value.

    To illustrate, I'll give you a complete example.

    Model and Screen

    I've modeled a Cliente class as an example like this:

    public class Cliente
    {
        [Key]
        [DisplayName("Identificador do Cliente")]
        public Guid ClienteId { get; set; }
    
        [Required]
        [DisplayName("Nome do Cliente")]
        public String Nome { get; set; }
        [Required]
        [DisplayName("Nome Fantasia")]
        public String Fantasia { get; set; }
    }
    

    That is, each property of the Cliente class has an attribute [DisplayName] ". This attribute will be what I'm going to display to the user.

    Once you've done this, I can make the following code to popular make up "Search Fields":

            var camposPesquisa = typeof(Cliente).GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
                               BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
                               .Select(p => new {
                                   Valor = p.Name,
                                   Texto = p.GetCustomAttribute<DisplayNameAttribute>().DisplayName
                               }).ToList();
    
            comboBoxCampoPesquisa.ValueMember = "Valor";
            comboBoxCampoPesquisa.DisplayMember = "Texto";
            comboBoxCampoPesquisa.DataSource = camposPesquisa;
    

    That is, my screen will display the values of [DisplayName] , but the values that will go to the code are the names of my fields:

    IcandothesamethingfortheconditionbysettingaEnumCondicaoandputtingattributes [Display] in them:

    public enum Condicao
    {
        [Display(Name = "Igual")]
        Igual,
        [Display(Name = "Diferente")]
        Diferente,
        [Display(Name = "Maior")]
        Maior,
        [Display(Name = "Menor")]
        Menor,
        [Display(Name = "Maior ou Igual")]
        MaiorOuIgual,
        [Display(Name = "Menor ou Igual")]
        MenorOuIgual
    }
    

    To extract the attribute from Enums , you will need an extension method:

    public static class EnumExtensions
    {
        public static TAttribute GetAttribute<TAttribute>(this Enum enumValue)
                where TAttribute : Attribute
        {
            return enumValue.GetType()
                            .GetMember(enumValue.ToString())
                            .First()
                            .GetCustomAttribute<TAttribute>();
        }
    }
    

    To use it like this:

            var condicoes = Enum.GetValues(typeof(Condicao))
                .Cast<Condicao>()
                .Select(c => new
                {
                    Valor = c.ToString(),
                    Texto = c.GetAttribute<DisplayAttribute>().Name
                })
                .ToList();
    
            comboBoxCondicao.ValueMember = "Valor";
            comboBoxCondicao.DisplayMember = "Texto";
            comboBoxCondicao.DataSource = condicoes;
    

    And then:

    Grid

    I'massumingGridinitializationisdoneintheOnLoadeventofyourForm

    protectedoverridevoidOnLoad(EventArgse){base.OnLoad(e);context.Clientes.Load();clienteBindingSource.DataSource=context.Clientes.Local.ToBindingList();...}

    OnlywiththisIhavethedatasearchanddueobservationbythemthroughthecontextoftheEntityFramework.Thatdone,IneedtoputaCheckBoxandaneventsothatittriggersthefilteringattheappropriatetime:

    privatevoidcheckBoxFiltrar_CheckedChanged(objectsender,EventArgse){Filtrar(checkBoxFiltrar.Checked);}

    Justasatest,Ididthefilteringbynameasfollows:

    protectedvoidFiltrar(boolcheckFiltrar){if(checkFiltrar)clienteBindingSource.DataSource=context.Clientes.Where(c=>c.Nome==textBoxValor.Text).ToList();elseclienteBindingSource.DataSource=context.Clientes.Local.ToBindingList();dataGridView.Refresh();}

    Hereisthestartingpointforamorerobustlogic.Therearetwowaystodothis:byusingthe System.Linq.Dynamic library or by mounting Expressions . For this answer I will use the first one (which basically does the same thing as the second).

    Dynamic Predicates

    Let's just build the dynamic predicate for Condicao.Igual :

        protected void Filtrar(bool checkFiltrar)
        {
            if (checkFiltrar)
                // clienteBindingSource.DataSource = context.Clientes.Where(c => c.Nome == textBoxValor.Text).ToList();
                clienteBindingSource.DataSource = context.Clientes
                    .Where(comboBoxCampoPesquisa.SelectedValue.ToString() + " == @0", textBoxValor.Text)
                    .ToList();
            else
                clienteBindingSource.DataSource = context.Clientes.Local.ToBindingList();
    
            dataGridView.Refresh();
        }
    

    Checking if it works:

    Finally,sinceIwanttosearchnotfortheexacttext,butforapartofit,Icandothefollowing:

    protectedvoidFiltrar(boolcheckFiltrar){if(checkFiltrar)//clienteBindingSource.DataSource=context.Clientes.Where(c=>c.Nome==textBoxValor.Text).ToList();clienteBindingSource.DataSource=context.Clientes//.Where(comboBoxCampoPesquisa.SelectedValue.ToString()+" == @0", textBoxValor.Text)
                    .Where(comboBoxCampoPesquisa.SelectedValue.ToString() + ".Contains(@0)", textBoxValor.Text)
                    .ToList();
            else
                clienteBindingSource.DataSource = context.Clientes.Local.ToBindingList();
    
            dataGridView.Refresh();
        }
    

    Converting Enum to a String operator stays as a homework.

        
    17.04.2017 / 22:43