none
Obtener la descripción de un enum en una consulta linq RRS feed

  • Pregunta

  • Hola

    Trabajo con C#, Windows forms, Visual Studio 2019

    Tengo una consulta de selección en la cual uno de los campos es el valor del enum que puede ser 1, 2, 3 al momento de recuperar los datos deseo mostrar la descripción del enum en este caso es Estado = 3 el cual tiene una descripción "Emitido" deseo mostrar la descripción en vez del 3.

    Esta es mi consulta.

    using (var context = new BusinessContext())
                {
                    var result = from ov in context.OrdenVentas
                                 join c in context.Clientes on ov.ClienteId equals c.ClienteId
                                 where
                                     (filter.Codigo == null || ov.CodigoNumerico.Contains(filter.Codigo))
                                     &&
                                     (!filter.ClienteId.HasValue || ov.ClienteId.Equals(filter.ClienteId.Value))
                                     &&
                                     (filter.FechaEmision == null || ov.FechaEmision >= filter.FechaEmision)
                                     &&
                                     (filter.FechaCaducidad == null || ov.FechaCaducidad <= filter.FechaCaducidad)
                                     &&
                                     ov.Estado == EstadoOrdenVenta.Emitido
                                 select
                                     new UniversalExtend()
                                     {
                                         Id = ov.OrdenVentaId,
                                         NumeroComprobante = ov.NumeroComprobante,
                                         Descripcion = c.RazonSocial,
                                         FechaEmision = ov.FechaEmision,
                                         FechaCaducidad = ov.FechaCaducidad,
                                         Estado = Enum.GetName(typeof(EstadoOrdenVenta), ov.Estado),
                                         Total = ov.Total
                                     };
                    return result.ToList();
                }

    Enum

    public enum EstadoOrdenVenta : int
        {
            [Description("EMITIDO")]
            Emitido = 1,
            [Description("APROBADO")]
            Aprobado = 2,
            [Description("ATENDIDO")]
            Atendido = 3
        }

    El error que obtengo en la consulta es el siguiente:

    LINQ to Entities does not recognize the method 'System.String GetName(System.Type, System.Object)' method, and this method cannot be translated into a store expression.

    ¿Como puedo obtener lo que deseo?

    Saludos!

     

    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú


    martes, 18 de junio de 2019 14:53

Respuestas

  • hola

    El tema es que no puede poner una funcion GetDescription() como parte del linq que se va a transformar el una query sql, no sabra como convertirlo

    Pero podrias ponerlo dentro de la clase

    public class UniversalExtend{
    
       //resto propiedades
    
       public EstadoOrdenVenta Estado {get;set;}
    
       public string EstadoDescripcion{
    
            get{ return GetDescription(this.Estado); }
    
       }
    
    }


    si la propiedad que mapeas en EF es un enum, puedes poner una propiedad de solo lectura que devuelva a descripcion

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila martes, 18 de junio de 2019 20:07
    martes, 18 de junio de 2019 15:58
  • hola

    >>La propiedad es de solo lectura, ¿como lo utilizo?

    como la utlizas? es una propiedad la accedes para tomar su valor  como cualquier otra propiedad

    No se porque pussiste a GetDescription() dentro de esa clase, eso va por fuera como un helper o clase static que cruza a toda la app, no a esa clase

    

    >>Al ser de solo lectura lo único que se me ocurrio fue poner la propiedad en el PropertyName que alimenta mi Dgv.

    si eso es correcto

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila martes, 18 de junio de 2019 20:08
    martes, 18 de junio de 2019 18:49

Todas las respuestas

  • Hola

    Encontré una solución pero no la veo optima, conseguir la descripción del enum por fuera

    public string GetDescription(Enum value)
            {
                return
                    value
                        .GetType()
                        .GetMember(value.ToString())
                        .FirstOrDefault()
                        ?.GetCustomAttribute<DescriptionAttribute>()
                        ?.Description
                    ?? value.ToString();
            }

    Aplicandolo en la consulta

    using (var context = new BusinessContext())
                {
                    var estado = GetDescription(EstadoOrdenVenta.Emitido); == Esta quemado en el código
                    var result = from ov in context.OrdenVentas
                                 join c in context.Clientes on ov.ClienteId equals c.ClienteId
                                 where
                                     (filter.Codigo == null || ov.CodigoNumerico.Contains(filter.Codigo))
                                     &&
                                     (!filter.ClienteId.HasValue || ov.ClienteId.Equals(filter.ClienteId.Value))
                                     &&
                                     (filter.FechaEmision == null || ov.FechaEmision >= filter.FechaEmision)
                                     &&
                                     (filter.FechaCaducidad == null || ov.FechaCaducidad <= filter.FechaCaducidad)
                                     &&
                                     ov.Estado == EstadoOrdenVenta.Emitido
                                 select
                                     new UniversalExtend()
                                     {
                                         Id = ov.OrdenVentaId,
                                         NumeroComprobante = ov.NumeroComprobante,
                                         Descripcion = c.RazonSocial,
                                         FechaEmision = ov.FechaEmision,
                                         FechaCaducidad = ov.FechaCaducidad,
                                         //Estado = Enum.GetName(typeof(EstadoOrdenVenta), ov.Estado),
                                         Estado = estado,
                                         Total = ov.Total
                                     };
                    return result.ToList();
                }
    ¿Hay alguna mejor solución?

    Saludos!


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    martes, 18 de junio de 2019 15:12
  • hola

    El tema es que no puede poner una funcion GetDescription() como parte del linq que se va a transformar el una query sql, no sabra como convertirlo

    Pero podrias ponerlo dentro de la clase

    public class UniversalExtend{
    
       //resto propiedades
    
       public EstadoOrdenVenta Estado {get;set;}
    
       public string EstadoDescripcion{
    
            get{ return GetDescription(this.Estado); }
    
       }
    
    }


    si la propiedad que mapeas en EF es un enum, puedes poner una propiedad de solo lectura que devuelva a descripcion

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila martes, 18 de junio de 2019 20:07
    martes, 18 de junio de 2019 15:58
  • Hola @Leandro

    La propiedad es de solo lectura, ¿como lo utilizo?

    Tengo lo siguiente, en la clase UniversalExtend

    public EstadoOrdenVenta EstadoId { get; set; }
    
            public string EstadoDescripcion
            {
                get { return GetDescription(this.EstadoId); }
            }
            public decimal Total { get; set; }
    
            public string GetDescription(Enum value)
            {
                return
                    value
                        .GetType()
                        .GetMember(value.ToString())
                        .FirstOrDefault()
                        ?.GetCustomAttribute<DescriptionAttribute>()
                        ?.Description
                    ?? value.ToString();
            }

    Al ser de solo lectura lo único que se me ocurrio fue poner la propiedad en el PropertyName que alimenta mi Dgv.

    using (var context = new BusinessContext())
                {
                    //var estado = GetDescription(EstadoOrdenVenta.Emitido);
                    var result = from ov in context.OrdenVentas
                                 join c in context.Clientes on ov.ClienteId equals c.ClienteId
                                 where
                                     (filter.Codigo == null || ov.CodigoNumerico.Contains(filter.Codigo))
                                     &&
                                     (!filter.ClienteId.HasValue || ov.ClienteId.Equals(filter.ClienteId.Value))
                                     &&
                                     (filter.FechaEmision == null || ov.FechaEmision >= filter.FechaEmision)
                                     &&
                                     (filter.FechaCaducidad == null || ov.FechaCaducidad <= filter.FechaCaducidad)
                                     &&
                                     ov.Estado == EstadoOrdenVenta.Emitido
                                 select
                                     new UniversalExtend()
                                     {
                                         Id = ov.OrdenVentaId,
                                         NumeroComprobante = ov.NumeroComprobante,
                                         Descripcion = c.RazonSocial,
                                         FechaEmision = ov.FechaEmision,
                                         FechaCaducidad = ov.FechaCaducidad,
                                         //Estado = Enum.GetName(typeof(EstadoOrdenVenta), ov.Estado),
                                         //Estado = estado,
                                         EstadoId = ov.Estado,
                                         Total = ov.Total
                                     };
                    return result.ToList();
                }

    De que manera la puedo poner en ese select para que lleve la info.

    Saludos


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    martes, 18 de junio de 2019 16:17
  • hola

    >>La propiedad es de solo lectura, ¿como lo utilizo?

    como la utlizas? es una propiedad la accedes para tomar su valor  como cualquier otra propiedad

    No se porque pussiste a GetDescription() dentro de esa clase, eso va por fuera como un helper o clase static que cruza a toda la app, no a esa clase

    

    >>Al ser de solo lectura lo único que se me ocurrio fue poner la propiedad en el PropertyName que alimenta mi Dgv.

    si eso es correcto

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila martes, 18 de junio de 2019 20:08
    martes, 18 de junio de 2019 18:49