none
filtros dinamicos con Like o contains usando dynamic linq RRS feed

  • Pregunta

  • Hola gente:

    Estoy probando la librería dynamic para linq, y estoy tratando de filtrar los datos de una tabla dinámicamente en función de los campos que se completan en un formulario, (lo típico), pero tengo un problema y es usar LIKE en el where.

    No se si es posible usar algo asi  (a mi da error):

    miLinqDataContextlinq = newmiLinqDataContext();

    if(paramNombre!="")

    stringw = "nombre like '%"+paramNombre+"%'";

    List<personas> lista =linq.personas.Where(w).ToList<personas>();

    Esto es una ejemplo simple de lo que busco.

    Alguna ayuda?

    Muchas gracias


    Juanjo

    lunes, 29 de junio de 2015 16:24

Respuestas

  • Hola,

    Para que quede claro lo que menciono te cito algo similar (LinQ en MVC) con una problemática similar a la que tienes.

    var students = from s in db.Students
                      select s;
       switch (sortOrder)
       {
          case "name_desc":
             students = students.OrderByDescending(s => s.LastName);
             break;
          case "Date":
             students = students.OrderBy(s => s.EnrollmentDate);
             break;
          case "date_desc":
             students = students.OrderByDescending(s => s.EnrollmentDate);
             break;
          default:
             students = students.OrderBy(s => s.LastName);
             break;
       }
       return View(students.ToList());

    "...The method uses LINQ to Entities to specify the column to sort by. The code creates an IQueryable variable before the switch statement, modifies it in the switch statement, and calls the ToList method after the switchstatement. When you create and modify IQueryable variables, no query is sent to the database. The query is not executed until you convert the IQueryable object into a collection by calling a method such as ToList. Therefore, this code results in a single query that is not executed until the return View statement."

    • Marcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 17:39
    • Desmarcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 17:39
    • Marcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 19:03
    lunes, 29 de junio de 2015 17:28

Todas las respuestas

  • Hola,

    Puedes hacer uso de contains

    var lista = linq.personas.Where(a => a.nombre.contains(paramNombre)).ToList();


    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.


    Willams Morales
    Arequipa - PERÚ


    lunes, 29 de junio de 2015 16:35
  • Gracias por la respuesta pero no me vale

    lo que busco es la traducción de esto:

    var lista = linq.personas.Where(a => a.nombre.contains(paramNombre));

    a dynamics linq

    Lo que has escrito no va muy bien cuando tienes tablas con 10.000 registros y 15 filtros (que es como lo hacia hasta ahora) porque primero se trae los 10.000 registros y luego filtra, yo busco que solo me traiga los registros que complen el "contains"

    Gracias, igualmente


    Juanjo

    lunes, 29 de junio de 2015 16:39
  • Hola,

    ¿cómo determinas que LinQ trae todos los registros y luego filtra? Suena ilógico, ¿has intentado utilizar el Profiler para determinar la consulta t-sql que arma según las instrucciones linq?



    lunes, 29 de junio de 2015 16:50
  • Hola,

    Cuando tienes los filtros estáticos y sabes que siempre van a completar todos los filtros, vale.

    Pero si en un formulario tienes 5 campos, los cuales puedes completarlos todos o no, tu como filtras?

    yo veo dos opciones:

    -expresiones lamba

    -traes todos los datos y luego filtras, algo asi:

    var lista = linq.personas;

    if (paramNombre!="") lista=lista.Where(p=>p.nombreContains(paramNombre);

    if(paramEdad!="") lista=lista.where(p=>p.edad==paramEdad);

    .....(resto de filtros)

    Pero de primeras te tienes que traer todos los datos.

    Con dynamic puedes hacer:

    w=" true"

    if (paramNombre!="") w+=" and nombre ='"+paramNombre+"'";

    if(paramEdad!="") w+=" and edad="+paramEdad;

    var lista = milinq.personas.Where(w);

    Ejecutas el where en la consulta, no te traes todo, pero el like no me funciona.

    Saludos

    Si hay otra forma también me vale


    Juanjo

    lunes, 29 de junio de 2015 16:58
  • Hola Juanjo,

    Vuelvo a preguntar, ¿cómo determinas que LinQ se trae todos los datos desde que empiezas a "lanzar" las primeras instrucciones?

    A ver, cuando se crea una instrucción LinQ la query no es enviada a la base de datos. La query no es ejecutada hasta que el objeto IQueryable se convierta en una colección como por ejemplo con una llamada a ToList().

    A ver:

    /*Hasta aquí la query no ejecuta nada en la bd*/
    var lista = linq.personas;
    
    /*Hasta aquí tampoco se ejecuta nada*/
    if (paramNombre != "")
      lista = lista.where...
    
    /*es recién aquí que la consulta se ejecuta contra la bd*/
    lista = lista.ToList();

    Si la solución propuesta atendió su consulta no olvide marcarla como respuesta.

    Willams Morales
    Arequipa - PERÚ


    lunes, 29 de junio de 2015 17:15
  • Hola,

    Para que quede claro lo que menciono te cito algo similar (LinQ en MVC) con una problemática similar a la que tienes.

    var students = from s in db.Students
                      select s;
       switch (sortOrder)
       {
          case "name_desc":
             students = students.OrderByDescending(s => s.LastName);
             break;
          case "Date":
             students = students.OrderBy(s => s.EnrollmentDate);
             break;
          case "date_desc":
             students = students.OrderByDescending(s => s.EnrollmentDate);
             break;
          default:
             students = students.OrderBy(s => s.LastName);
             break;
       }
       return View(students.ToList());

    "...The method uses LINQ to Entities to specify the column to sort by. The code creates an IQueryable variable before the switch statement, modifies it in the switch statement, and calls the ToList method after the switchstatement. When you create and modify IQueryable variables, no query is sent to the database. The query is not executed until you convert the IQueryable object into a collection by calling a method such as ToList. Therefore, this code results in a single query that is not executed until the return View statement."

    • Marcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 17:39
    • Desmarcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 17:39
    • Marcado como respuesta Juanjo_16v lunes, 29 de junio de 2015 19:03
    lunes, 29 de junio de 2015 17:28
  • Igual estaba equivocado, la verdad es que usaba cada vez que hacia un where un ToList, por eso me iria tan lento y mal.

    Lo probare.

    Por si ha alguien le interesa hay un contains para dynamic, se usa igual:

    string w = "nombre.Contains(\""+paramNombre+"\")";

    List<personas> lista = linq.personas.Where(w).ToList<personas>();


    Juanjo

    lunes, 29 de junio de 2015 17:39
  • He  hecho una prueba y al probar:

    /*Hasta aquí la query no ejecuta nada en la bd*/
    var lista = linq.personas;

    /*Hasta aquí tampoco se ejecuta nada*/
    if (paramNombre != "")
      lista
    = lista.where(p=>p.nombre.Contains(paramNombre));

    AQUI SE PRODUCE UN ERROR:

    No se puede convertir implícitamente el tipo 'System.Linq.IQueryable<personas>' en 'System.Data.Entity.DbSet<personas>'. Ya existe una conversión explícita (compruebe si le falta una conversión)

    /*es recién aquí que la consulta se ejecuta contra la bd*/
    lista
    = lista.ToList();

    Que falla? porque si tengo que poner .ToList() para que funcione estoy como al principio


    Juanjo

    lunes, 29 de junio de 2015 17:50
  • Hola,

    ¿Podrías mostrar el tipo de la variable lista? Vi que lo estabas tipando, declaralo con var. var inferirá el tipo correcto según los valores devueltos.

    lunes, 29 de junio de 2015 18:11
  • Con esto ya no falla

    IQueryable<persona> lista = linq.personas;

    /*Hasta aquí tampoco se ejecuta nada*/
    if (paramNombre != "")
       lista = lista.where(p=>p.nombre.Contains(paramNombre));


    /*es recién aquí que la consulta se ejecuta contra la bd*/
     lista = lista.ToList();


    Juanjo

    lunes, 29 de junio de 2015 19:02
  • Hola juanjo,

    Como sugerencia déjalo con un tipo var ímplicito, deja que el compilador determine el tipo, lo hará sin ningún coste adicional.

    lunes, 29 de junio de 2015 19:20
  • hola,

    puedes decirme como hacerlo? es por probar una cosa.

    Saludos


    Juanjo

    martes, 30 de junio de 2015 5:59
  • Hola,

    Es decir, no declares

    IQueryable<persona> lista = linq.personas.

    Hazlo de la siguiente manera:

    var lista = linq.personas;

    martes, 30 de junio de 2015 6:05
  • Hola

    Asi es como lo hice al principio, pero me da este error

    var lista = linq.personas;
    if (paramNombre != "")
      lista
    = lista.where(p=>p.nombre.Contains(paramNombre));<===AQUI SE PRODUCE UN ERROR:

    No se puede convertir implícitamente el tipo 'System.Linq.IQueryable<personas>' en 'System.Data.Entity.DbSet<personas>'. Ya existe una conversión explícita (compruebe si le falta una conversión)

    Por eso lo cambie por  IQueryable<persona> lista = linq.personas;

    Gracias


    Juanjo

    martes, 30 de junio de 2015 6:55