none
Filtros condicionales usando Linq RRS feed

  • Pregunta

  • Hola

    Trabajo en una app Windows Forms, SQL Server 2014 Express Edition, EF enfoque code first

    Tengo un filtro condicional que permite valores null, el detalle es que cuando no le mando parámetros quiero decir que todos los parámetros que mando son null me trae registros de la db. Lo normal sería si no estoy mandando parámetros para que haga una búsqueda no debe traer nada.

    Mi consulta linq es la siguiente

    using (var context = new BusinessContext())
                {
                    var result = from oi in context.OrdenInventarios
                                 where
                                 (filter.NumeroOrden == null || oi.NumeroOrden.Contains(filter.NumeroOrden))
                                 &&
                                 (!filter.EstadoOrden.HasValue || oi.EstadoOrden == filter.EstadoOrden)
                                 &&
                                 (filter.FechaEmisionDesde == null || oi.Fecha >= DbFunctions.TruncateTime(filter.FechaEmisionDesde))
                                 &&
                                 (filter.FechaEmisionHasta == null || oi.Fecha <= DbFunctions.TruncateTime(filter.FechaEmisionHasta))
                                 select
                                 new UniversalExtend()
                                 {
                                     Id = oi.OrdenInventarioId,
                                     NumeroComprobante = oi.NumeroOrden,
                                     FechaEmision = oi.Fecha,
                                     EstadoOrden = oi.EstadoOrden
                                 };
                    return result.ToList();
                }

    Y haciendo un seguimiento con el SQL Profiler me arroja la siguiente consulta SQL

    exec sp_executesql N'SELECT 
        [Extent1].[OrdenInventarioId] AS [OrdenInventarioId], 
        [Extent1].[NumeroOrden] AS [NumeroOrden], 
        [Extent1].[Fecha] AS [Fecha], 
        [Extent1].[EstadoOrden] AS [EstadoOrden]
        FROM [dbo].[OrdenInventarios] AS [Extent1]
        WHERE ((@p__linq__0 IS NULL) 
    	OR 
    	([Extent1].[NumeroOrden] LIKE @p__linq__1 ESCAPE ''~'')) AND (@p__linq__2 IS NULL OR @p__linq__3 =  CAST( [Extent1].[EstadoOrden] AS int)) AND ((@p__linq__4 IS NULL) 
    	OR 
    	([Extent1].[Fecha] >= (convert (datetime2, convert(varchar(255), @p__linq__5, 102) ,  102)))) 
    	AND ((@p__linq__6 IS NULL) 
    	OR 
    	([Extent1].[Fecha] <= (convert (datetime2, convert(varchar(255), @p__linq__7, 102) ,  102))))',
    	N'@p__linq__0 nvarchar(4000),@p__linq__1 varchar(8000),@p__linq__2 int,@p__linq__3 int,
    	@p__linq__4 datetime2(7),@p__linq__5 datetime2(7),
    	@p__linq__6 datetime2(7),@p__linq__7 datetime2(7)',
    	@p__linq__0=N'',
    	@p__linq__1='%%',
    	@p__linq__2=NULL,
    	@p__linq__3=NULL,
    	@p__linq__4=NULL,
    	@p__linq__5=NULL,
    	@p__linq__6=NULL,
    	@p__linq__7=NULL

    Según no me este equivocando en la consulta no hay parámetro alguno, ¿no se porque me trae los registros que hay en la tabla?.

    Saludos!

     

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

    jueves, 6 de febrero de 2020 16:39

Respuestas

  • >>He comentado cada uno de las condicionales y me sigue trayendo datos

    ok, pero eso esta bien, veo todos los parametros en null

    ahora si le pasas un valor en alguno, aplica el filtro para ese parametro que asignas

    si todo funciona puede que usar un string comparandolo con null no se lleve muy bien, por eso deberias aplicar la tecnica que comente antes de tener una variable bool adicional para resolver cuando es opcional el parametro string

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 7 de febrero de 2020 3:23
  • hola

    >>Pero los string no aceptan valores nulos me refiero a esto public string? NumeroOrden ....

    el string si permite null, el tema es ver como lo toma linq

    Si quitas esta linea

    (filter.NumeroOrden == null ||oi.NumeroOrden.Contains(filter.NumeroOrden))

    del linq la query funciona y retorna registros ?  solo para asegurar que sea ese el parametro del conflicto, pero que el resto funcione de forma condiciona

    Quizas para ese filtro debas tener dos parametros uno del tipo bool (HasNumberOrder ) y el otro como string con el valor

    filter.NumeroOrden = valor;
    
    filter.HasNumberoOrder =  !string.IsNullOrEmpty(txtNumeroOrden.Text);
    Entonces en el linq quedaria
     (filter.HasNumeroOrden || oi.NumeroOrden.Contains(filter.NumeroOrden))

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 6 de febrero de 2020 23:11
  • hola

    >>Estoy usando DbFunctions.TruncateTime pero no me esta trayendo la información que necesito.

    vayamos por parte porque se mezcla todo

    estabamos con el NumeroOrden, eso se resolvio? trata de quemar etapas para resolver problemas todo junto es imposible entender de donde salen las cosas que cambias

    Veo que ya no defines una vlaidacion null en el NumeroOrden, eso porque fue? ya no es un parametro opcional

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    viernes, 7 de febrero de 2020 19:39
  • >>el detalle es que si mando todos los parámetros null me trae toda la tabla.

    Pero si pones un valor en NumeroOrden, puedes validar que cambia el HasNumeroOrden y permite filtrar por ese numero de orden ?

    quita del linq todo los demas parametros primero asegurate que uno funciona

    despues peude ir agregando el resto, si quieres resolver todo de una no vas a poder, aplica el divide y venceras

    saludos



    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila viernes, 7 de febrero de 2020 23:49
    viernes, 7 de febrero de 2020 19:49

Todas las respuestas

  • Hola Pedro Ávila

     

    Gracias por levantar tu consulta en los foros de MSDN. Con respecto a la misma, te comparto a continuación el siguiente enlace en el cual encontraras un caso similar al que nos estás reportando que te puede servir para entender mejor la estructura de los condicionales

     

    https://social.msdn.microsoft.com/Forums/es-ES/55f82677-6276-4fb8-a40a-8491ab5ff70f/filtrar-con-condiciones-en-linq?forum=vcses

     

    Por favor déjame saber si puedo ofrecerte una mejor respuesta

    Gracias por usar los foros de MSDN.

     

    Diana

     

     ____

     

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde. 

     

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.  

     

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft.

    jueves, 6 de febrero de 2020 19:35
    Moderador
  • hola

    >>no me este equivocando en la consulta no hay parámetro alguno,

    veo dos parametro que si estan aplicando

    @p__linq__0=N'',
    @p__linq__1='%%',

    esos no estan en NULL

    segun entiendo se relaciona con el NumeroOrden

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 6 de febrero de 2020 21:28
  • Hola @Leandro

    Tengo un string que es NumeroOrden el cual si esta vació le mando un null

    var filter = new CriteriaOrdenInventario()
                {
                    NumeroOrden = !string.IsNullOrEmpty(txtNumeroOrden.Text) ? txtNumeroOrden.Text : null,
                    EstadoOrden = (int)(cboEstadoOrden.SelectedValue) == -1 ? (EstadoOrden?)null : (EstadoOrden)cboEstadoOrden.SelectedValue,
                    FechaEmisionDesde = chkFechaEmisionDesde.Checked ? (DateTime?)dtpFechaEmisionDesde.Value : null,
                    FechaEmisionHasta = chkFechaEmisionHasta.Checked ? (DateTime?)dtpFechaEmisionHasta.Value : null
                };

    NumeroOrden = txtNumeroOrden lo cambie por la siguiente linea

    NumeroOrden = !string.IsNullOrEmpty(txtNumeroOrden.Text) ? txtNumeroOrden.Text : null,

    Pero los string no aceptan valores nulos me refiero a esto public string? NumeroOrden ....

    Query SQL

    exec sp_executesql N'SELECT 
        [Extent1].[OrdenInventarioId] AS [OrdenInventarioId], 
        [Extent1].[NumeroOrden] AS [NumeroOrden], 
        [Extent1].[Fecha] AS [Fecha], 
        [Extent1].[EstadoOrden] AS [EstadoOrden]
        FROM [dbo].[OrdenInventarios] AS [Extent1]
        WHERE ((@p__linq__0 IS NULL) 
    	OR
    	 ([Extent1].[NumeroOrden] LIKE @p__linq__1 ESCAPE ''~'')) AND (@p__linq__2 IS NULL 
    	OR 
    	 @p__linq__3 =  CAST( [Extent1].[EstadoOrden] AS int)) AND ((@p__linq__4 IS NULL) 
    	OR 
    	 ([Extent1].[Fecha] >= (convert (datetime2, convert(varchar(255), @p__linq__5, 102) ,  102)))) AND ((@p__linq__6 IS NULL) 
    	OR 
    	 ([Extent1].[Fecha] <= (convert (datetime2, convert(varchar(255), @p__linq__7, 102) ,  102))))',
    	 N'@p__linq__0 nvarchar(4000),
    	 @p__linq__1 varchar(8000),
    	 @p__linq__2 int,
    	 @p__linq__3 int,
    	 @p__linq__4 datetime2(7),
    	 @p__linq__5 datetime2(7),
    	 @p__linq__6 datetime2(7),
    	 @p__linq__7 datetime2(7)',
    	 @p__linq__0=NULL,
    	 @p__linq__1=NULL,
    	 @p__linq__2=NULL,
    	 @p__linq__3=NULL,
    	 @p__linq__4=NULL,
    	 @p__linq__5=NULL,
    	 @p__linq__6=NULL,
    	 @p__linq__7=NULL

    El problema es que si no le mando parámetros lo normal no debe traer nada pero esta trayendo registros, es lo que quiero solucionar.

    Saludos! 


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

    jueves, 6 de febrero de 2020 21:58
  • hola

    >>Pero los string no aceptan valores nulos me refiero a esto public string? NumeroOrden ....

    el string si permite null, el tema es ver como lo toma linq

    Si quitas esta linea

    (filter.NumeroOrden == null ||oi.NumeroOrden.Contains(filter.NumeroOrden))

    del linq la query funciona y retorna registros ?  solo para asegurar que sea ese el parametro del conflicto, pero que el resto funcione de forma condiciona

    Quizas para ese filtro debas tener dos parametros uno del tipo bool (HasNumberOrder ) y el otro como string con el valor

    filter.NumeroOrden = valor;
    
    filter.HasNumberoOrder =  !string.IsNullOrEmpty(txtNumeroOrden.Text);
    Entonces en el linq quedaria
     (filter.HasNumeroOrden || oi.NumeroOrden.Contains(filter.NumeroOrden))

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 6 de febrero de 2020 23:11
  • Hola

    He quitado NumeroOrden de la consulta linq y me sigue trayendo datos

    exec sp_executesql N'SELECT 
        [Extent1].[OrdenInventarioId] AS [OrdenInventarioId], 
        [Extent1].[NumeroOrden] AS [NumeroOrden], 
        [Extent1].[Fecha] AS [Fecha], 
        [Extent1].[EstadoOrden] AS [EstadoOrden]
        FROM [dbo].[OrdenInventarios] AS [Extent1]
        WHERE (@p__linq__0 IS NULL 
    	OR 
    	 @p__linq__1 =  CAST( [Extent1].[EstadoOrden] AS int)) AND ((@p__linq__2 IS NULL) 
    	OR
    	 ([Extent1].[Fecha] >= (convert (datetime2, convert(varchar(255), @p__linq__3, 102) ,  102)))) AND ((@p__linq__4 IS NULL) 
    	OR
    	 ([Extent1].[Fecha] <= (convert (datetime2, convert(varchar(255), @p__linq__5, 102) ,  102))))',
    	 N'@p__linq__0 int,
    	 @p__linq__1 int,
    	 @p__linq__2 datetime2(7),
    	 @p__linq__3 datetime2(7),
    	 @p__linq__4 datetime2(7),
    	 @p__linq__5 datetime2(7)',
    	 @p__linq__0=NULL,
    	 @p__linq__1=NULL,
    	 @p__linq__2=NULL,
    	 @p__linq__3=NULL,
    	 @p__linq__4=NULL,
    	 @p__linq__5=NULL

    He comentado cada uno de las condicionales y me sigue trayendo datos


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


    jueves, 6 de febrero de 2020 23:43
  • >>He comentado cada uno de las condicionales y me sigue trayendo datos

    ok, pero eso esta bien, veo todos los parametros en null

    ahora si le pasas un valor en alguno, aplica el filtro para ese parametro que asignas

    si todo funciona puede que usar un string comparandolo con null no se lleve muy bien, por eso deberias aplicar la tecnica que comente antes de tener una variable bool adicional para resolver cuando es opcional el parametro string

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 7 de febrero de 2020 3:23
  • Hola

    En la fecha tengo problemas

    ahora si le pasas un valor en alguno, aplica el filtro para ese parametro que asignas

    Estoy usando DbFunctions.TruncateTime pero no me esta trayendo la información que necesito.

    Mi implementación es la siguiente:

    var filter = new CriteriaOrdenInventario()
                {
                    //NumeroOrden = !string.IsNullOrEmpty(txtNumeroOrden.Text) ? txtNumeroOrden.Text : null,
                    NumeroOrden = txtNumeroOrden.Text,
                    HasNumberOrder = !string.IsNullOrEmpty(txtNumeroOrden.Text),
                    EstadoOrden = (int)(cboEstadoOrden.SelectedValue) == -1 ? (EstadoOrden?)null : (EstadoOrden)cboEstadoOrden.SelectedValue,
                    FechaEmisionDesde = chkFechaEmisionDesde.Checked ? (DateTime?)dtpFechaEmisionDesde.Value.Date : null,
                    FechaEmisionHasta = chkFechaEmisionHasta.Checked ? (DateTime?)dtpFechaEmisionHasta.Value.Date : null
                };

    Query linq

    var result = from oi in context.OrdenInventarios
                                 where
                                 //(filter.NumeroOrden == null || oi.NumeroOrden.Contains(filter.NumeroOrden))
                                 (filter.HasNumberOrder || oi.NumeroOrden.Contains(filter.NumeroOrden))
                                 &&
                                 (!filter.EstadoOrden.HasValue || oi.EstadoOrden == filter.EstadoOrden.Value)
                                 &&
                                 (filter.FechaEmisionDesde == null || oi.Fecha >= DbFunctions.TruncateTime(filter.FechaEmisionDesde))
                                 &&
                                 (filter.FechaEmisionHasta == null || oi.Fecha <= DbFunctions.TruncateTime(filter.FechaEmisionHasta))
                                 select
                                 new UniversalExtend()
                                 {
                                     Id = oi.OrdenInventarioId,
                                     NumeroComprobante = oi.NumeroOrden,
                                     FechaEmision = oi.Fecha,
                                     EstadoOrden = oi.EstadoOrden
                                 };
                    return result.ToList();

    Nota: Estoy usando EF 6.2.0 ya que estoy usando la versión de .Net Framework 4.7.2, estoy usando el namespace using System.Data.Entity;

    En la base de datos tengo la siguiente fecha 2020-02-04 18:04:39 para poder obtener esta fecha en el filtro tengo que ingresar desde 04/02/2020 hasta 05/02/2020, ¿es correcto?, ¿no debería poner en los filtros desde 04/02/2020 hasta 04/02/2020

    ¿Por qué salen cuatro fechas?

    exec sp_executesql N'SELECT 
        [Extent1].[OrdenInventarioId] AS [OrdenInventarioId], 
        [Extent1].[NumeroOrden] AS [NumeroOrden], 
        [Extent1].[Fecha] AS [Fecha], 
        [Extent1].[EstadoOrden] AS [EstadoOrden]
        FROM [dbo].[OrdenInventarios] AS [Extent1]
        WHERE ((@p__linq__0 = 1) OR ([Extent1].[NumeroOrden] LIKE @p__linq__1 ESCAPE ''~'')) AND ((@p__linq__2 IS NULL) 
    	OR
    	 ([Extent1].[EstadoOrden] = @p__linq__3)) AND ((@p__linq__4 IS NULL) 
    	OR
    	 ([Extent1].[Fecha] >= (convert (datetime2, convert(varchar(255), @p__linq__5, 102) ,  102)))) AND ((@p__linq__6 IS NULL) 
    	OR
    	 ([Extent1].[Fecha] <= (convert (datetime2, convert(varchar(255), @p__linq__7, 102) ,  102))))',
    	 N'@p__linq__0 bit,
    	@p__linq__1 varchar(8000),
    	@p__linq__2 int,@p__linq__3 int,
    	@p__linq__4 datetime2(7),
    	@p__linq__5 datetime2(7),
    	@p__linq__6 datetime2(7),
    	@p__linq__7 datetime2(7)',
    	@p__linq__0=0,@p__linq__1='%%',
    	@p__linq__2=NULL,
    	@p__linq__3=NULL,
    	@p__linq__4='2020-02-04 00:00:00',
    	@p__linq__5='2020-02-04 00:00:00',
    	@p__linq__6='2020-02-04 00:00:00',
    	@p__linq__7='2020-02-04 00:00:00'


    Saludos!


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



    viernes, 7 de febrero de 2020 17:24
  • hola

    >>Estoy usando DbFunctions.TruncateTime pero no me esta trayendo la información que necesito.

    vayamos por parte porque se mezcla todo

    estabamos con el NumeroOrden, eso se resolvio? trata de quemar etapas para resolver problemas todo junto es imposible entender de donde salen las cosas que cambias

    Veo que ya no defines una vlaidacion null en el NumeroOrden, eso porque fue? ya no es un parametro opcional

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    viernes, 7 de febrero de 2020 19:39
  • Hola

    Si lo sigue siendo, lo que pasa que lo comente para comprobar las fechas, el detalle es que si mando todos los parámetros null me trae toda la tabla.

    Con la solución que me diste ingreso un número de orden y me trae toda la tabla pero con esta:

    (filter.NumeroOrden == null || oi.NumeroOrden.Contains(filter.NumeroOrden))

    Si me funciona bien.

    El detalle es que en todos los casos si le mando null me trae toda la tabla, después cuando le mando los parámetros si me trae lo que le pideo, excepto la fecha que si quiero la fecha 04/02/2020 tengo que poner un filtro de 04/02/2020 hasta 05/02/2020.

    Pero sigo sin entender por que si no le mando parámetros me trae toda la tabla.

    No se si lo mejor será quitar el TruncateTime y mandarle la fechas de las siguiente manera "desde las cero horas hasta las 23:59:59"

    Saludos!

     


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



    viernes, 7 de febrero de 2020 19:42
  • >>el detalle es que si mando todos los parámetros null me trae toda la tabla.

    Pero si pones un valor en NumeroOrden, puedes validar que cambia el HasNumeroOrden y permite filtrar por ese numero de orden ?

    quita del linq todo los demas parametros primero asegurate que uno funciona

    despues peude ir agregando el resto, si quieres resolver todo de una no vas a poder, aplica el divide y venceras

    saludos



    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila viernes, 7 de febrero de 2020 23:49
    viernes, 7 de febrero de 2020 19:49
  • Hola

    Usando HasNumeroOrden cuando no envio datos es false y cuando le asigno un dato es true hasta ahí esta bien todo pero cuando trae los datos me trae todos no el numero de orden especifico.

    (filter.HasNumberOrder || oi.NumeroOrden.Contains(filter.NumeroOrden))

    exec sp_executesql N'SELECT 
        [Extent1].[OrdenInventarioId] AS [OrdenInventarioId], 
        [Extent1].[NumeroOrden] AS [NumeroOrden], 
        [Extent1].[Fecha] AS [Fecha], 
        [Extent1].[EstadoOrden] AS [EstadoOrden]
        FROM [dbo].[OrdenInventarios] AS [Extent1]
        WHERE (@p__linq__0 = 1) OR ([Extent1].[NumeroOrden] LIKE @p__linq__1 ESCAPE ''~'')',
        N'@p__linq__0 bit,
    	@p__linq__1 varchar(8000)',
    	@p__linq__0=1,
    	@p__linq__1='%0000000002%'

    Hay un parametro 0 que tiene un valor 1 cuando lo quito si me trae lo que pido modificando desde el sql

    Solo se le esta preguntando por un dato especifico y trae toda la tabla.


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



    viernes, 7 de febrero de 2020 21:10
  • Leandro

    Tu técnica funciona!

    Cambiando el linq de : (filter.NumeroOrden == null || oi.NumeroOrden.Contains(filter.NumeroOrden))

    Por

    (filter.HasNumberOrder && oi.NumeroOrden.Contains(filter.NumeroOrden))

    El resultado es si le mando un parámetro me trae lo que le pido y si no le mando nada no me trae nada como debe ser.


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

    viernes, 7 de febrero de 2020 22:00
  • Leandro 

    Funciono

    Ya logre solucionar NumeroOrden y EstadoOrden la query de linq a cambiado

    var filter = new CriteriaOrdenInventario()
                {
                    NumeroOrden = txtNumeroOrden.Text,
                    HasNumberOrder = !string.IsNullOrEmpty(txtNumeroOrden.Text),
                    EstadoOrden = (EstadoOrden)cboEstadoOrden.SelectedValue,
                    HasEstadoOrden = (int)cboEstadoOrden.SelectedValue != (int)(-1).GetHashCode(),
                    FechaEmisionDesde = chkFechaEmisionDesde.Checked ? (DateTime?)dtpFechaEmisionDesde.Value : null,
                    FechaEmisionHasta = chkFechaEmisionHasta.Checked ? (DateTime?)dtpFechaEmisionHasta.Value: null
                };

    Query Linq

    var result = from oi in context.OrdenInventarios
                                 where
                                 (filter.HasNumberOrder && oi.NumeroOrden.Contains(filter.NumeroOrden))
                                 ||
                                 (filter.HasEstadoOrden && oi.EstadoOrden == filter.EstadoOrden)
                                 //||
                                 //(filter.FechaEmisionDesde == null || oi.Fecha >= DbFunctions.TruncateTime(filter.FechaEmisionDesde))
                                 //&&
                                 //(filter.FechaEmisionHasta == null || oi.Fecha < DbFunctions.TruncateTime(filter.FechaEmisionHasta))
                                 select
                                 new UniversalExtend()
                                 {
                                     Id = oi.OrdenInventarioId,
                                     NumeroComprobante = oi.NumeroOrden,
                                     FechaEmision = oi.Fecha,
                                     EstadoOrden = oi.EstadoOrden
                                 };
                    return result.ToList();

    Solo me falta solucionar lo de la fecha, eso lo voy a poner en otro hilo esto ya se hizo extenso.

    Gracias eres un crack!


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

    viernes, 7 de febrero de 2020 23:48