none
Query personalizado en WCF Ria Services para Silverlight RRS feed

  • Pregunta

  • HOLA, tengo una duda, el Visual Studio me autogeneró algunas consultas de mis entidades, las cuales luego tengo disponibles en el cuadro Orígenes de Datos, en cada una de las Entidades, por ejemplo:

    // TODO:
    // Considere la posibilidad de restringir los resultados de su método de consulta. Si necesita entradas adicionales, puede
    // agregar parámetros a este método o crear métodos de consulta adicionales con distintos nombres.
    // Para admitir la paginación tendrá que agregar ordenación a la consulta 'mtto_OrdenMtto'.
    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMtto()
    {
        return this.ObjectContext.mtto_OrdenMtto.Include("mtto_UnidadDetalle");
    }

    al cual le agregué que me incluyera una Entidad relacionada que es mtto_UnidadDetalle, así en una aplicación en la que hago referencia al resultado de este query, el usuario puede cambiar datos tanto de la Entidad principal (mtto_OrdenMtto) como de la incluida (mtto_UnidadDetalle) y en un mismo Submit se actualiza toda la información.

    Yo agregué un query que contiene relaciones entre varias tablas y recibe un parámetro:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)
    {
        ObjectSet<mtto_OrdenMtto> ordenes = this.ObjectContext.mtto_OrdenMtto;
        ObjectSet<mtto_OrdenMttoEstatus> Estatus = this.ObjectContext.mtto_OrdenMttoEstatus;
        ObjectSet<mtto_UnidadDetalle> unidades = this.ObjectContext.mtto_UnidadDetalle;
        ObjectSet<mtto_TipoMantenimiento> tipomttos = this.ObjectContext.mtto_TipoMantenimiento;
    
        var query =
              (from o in ordenes
               join e in Estatus on o.ID equals e.IDOrdenMtto
               join u in unidades on o.IDUni equals u.IDUni
               join t in tipomttos on u.IDTipoEquipo equals t.IDTipoEquipo
               where o.IDUni.Equals(_iduni)
               && !Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA") && oe.IDOrdenMtto == o.ID)
               select o).Distinct();
    
                return query.AsQueryable();
    }

    este funciona exacto como yo lo necesito, también lo puedo ver en la ventana de Orígenes de Datos y me da los registros de mi Entidad, la duda es, no sé cómo hacer para que también traiga incluido en el resultado la entidad relacionada (mtto_UnidadDetalle) como en el primer query que puse, pues si uso este segundo, no ve las propiedades de esta entidad

    Saludos y gracias


    cyndyrdz

    martes, 25 de noviembre de 2014 22:57

Respuestas

  • Esta parece ser mi opción, en realidad mi query debe regresar un solo registro pues una Unidad solo puede tener una Orden de Mtto abierta:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni, string _tipomantenimiento)
    {
        ObjectQuery<mtto_OrdenMtto> ordenes = this.ObjectContext.mtto_OrdenMtto;
        ObjectSet<mtto_OrdenMttoEstatus> Estatus = this.ObjectContext.mtto_OrdenMttoEstatus;
        ObjectSet<mtto_UnidadDetalle> unidades = this.ObjectContext.mtto_UnidadDetalle;
        ObjectSet<mtto_TipoMantenimiento> tipomttos = this.ObjectContext.mtto_TipoMantenimiento;
    
        mtto_OrdenMtto varquery;
    
        varquery =
                (from o in ordenes
                    join e in Estatus on o.ID equals e.IDOrdenMtto
                    join u in unidades on o.IDUni equals u.IDUni
                    join t in tipomttos on u.IDTipoEquipo equals t.IDTipoEquipo
                    where o.IDUni.Equals(_iduni)
                        && !Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA") && oe.IDOrdenMtto == o.ID)
                    select o).Distinct().FirstOrDefault();
    
        return this.ObjectContext.mtto_OrdenMtto.Include("mtto_UnidadDetalle").Where(o => o.ID.Equals(varquery.ID));
    }
    Y así si me incluye mtto_UnidadDetalle en el resultado, no sé si sea lo correcto, pero sí está funcionando bien....


    cyndyrdz

    viernes, 28 de noviembre de 2014 22:34

Todas las respuestas

  • Hola Cyndy

    Lo único que tienes que hacer es cambiar el select. 

    Te escribo la consulta

     var query =
              (from o in ordenes
               join e in Estatus on o.ID equals e.IDOrdenMtto
               join u in unidades on o.IDUni equals u.IDUni
               join t in tipomttos on u.IDTipoEquipo equals t.IDTipoEquipo
               where o.IDUni.Equals(_iduni)
               && !Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA") && oe.IDOrdenMtto == o.ID)
               select new { o,u}).Distinct();
    
                return query.AsQueryable();

    Saludos

    Aldo Flores Reyes

    @alduar

    miércoles, 26 de noviembre de 2014 8:36
  • Muchas gracias Aldo, eso ya lo había intentado, pero entonces no sé cómo se debería declarar el método, porque marca un conflicto con el tipo de dato que retorna, pues está declarado como:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)
    
    y dice que no puede convertir un anonimus a un mtto_OrdenMtto, no sé cómo declararlo....

    cyndyrdz

    miércoles, 26 de noviembre de 2014 14:37
  • Hola Cynthia.

    Lo que tienes que hacer es esto.

    public IEnumerable<object> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)
    public IEnumerable<dynamic> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)


    Saludos

    Aldo Flores Reyes

    @alduar


    • Editado alduar jueves, 27 de noviembre de 2014 12:24
    jueves, 27 de noviembre de 2014 12:19
  • Muchas gracias Aldo, pero cuando hago lo que me indicas en tu ultima respuesta (cambiar el IQueryable<tabla> en el tipo), ya no puedo ver el método desde la Ventana de Orígenes de Datos, así que cuando ejecuto la aplicación, me marca un error que dice: "El tipo MTTODomainContext no expone un método denominado 'GetMtto_OrdenMttoAbiertaxIDUniQuery'" ... :(

    cyndyrdz

    jueves, 27 de noviembre de 2014 16:39
  • Aldo, también intenté modificar mi query así:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)
    {
        ObjectSet<mtto_OrdenMttoEstatus> Estatus = this.ObjectContext.mtto_OrdenMttoEstatus;
        ObjectSet<mtto_UnidadDetalle> unidades = this.ObjectContext.mtto_UnidadDetalle;
        ObjectSet<mtto_TipoMantenimiento> tipomttos = this.ObjectContext.mtto_TipoMantenimiento;
    
        var query =
              (from o in this.ObjectContext.mtto_OrdenMtto.Include("mtto_UnidadDetalle")
               join e in Estatus on o.ID equals e.IDOrdenMtto
               join u in unidades on o.IDUni equals u.IDUni
               join t in tipomttos on u.IDTipoEquipo equals t.IDTipoEquipo
               where o.IDUni.Equals(_iduni)
               && !Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA") && oe.IDOrdenMtto == o.ID)
               select o).Distinct();
    
                return query.AsQueryable();
    }
    no marca ningún error, pero al ejecutarlo e inspeccionar el resultado la entidad mtto_UnidadDetalle viene en null... :(


    cyndyrdz

    jueves, 27 de noviembre de 2014 17:42
  • Hola Cyndy.

    He echo una prueba unitaria con uno objetos simples y funciona correctamente.

    Necesitas todos los campos de ambas entidades?.

    Porque lo que puedes hacer es un SELECT especifico con un nuevo objeto anónimo.

    Te adjunto una foto de la prueba realizada.

    public IEnumerable<Tuple<mtto_OrdenMtto,mtto_UnidadDetalle>> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni)
    {
    	...
    	
    }
    Esta es otra opción.

    Saludos

    Aldo Flores Reyes

    @alduar

    http://alduar.bloger.com


    • Editado alduar viernes, 28 de noviembre de 2014 11:14
    viernes, 28 de noviembre de 2014 11:02
  • Muchísimas gracias Aldo por todo tu apoyo, la verdad soy súper nueva en todo este ambiente y suelo sentirme tan perdida...sigo teniendo estas dudas:

    1. Para presentar mis datos en mi aplicación yo abro la ventana de Orígenes de Datos, allí me sale una lista con todas mis entidades, al seleccionar la entidad mtto_OrdenMtto, veo todos los métodos de acceso que he definido para ésta, el caso es que si cambio en mi método la firma de IQueryable<mtto_OrdenMtto> a cualquier otra cosa, entonces ese método no lo presenta en la ventana de Orígenes de Datos y no lo puedo usar arrastrándolo desde allí a un DataGrid, he construido algunos métodos Invoke, que uso con un InvokeOperation, así tendría que usar mi método si cambio la firma a como me indicas?

    2. Si pongo mi método como IEnumerable<Tuple<mtto_OrdenMtto, mtto_UnidadDetalle>> cómo debe ser el return?  es correcto: return (IEnumerable<Tuple<mtto_OrdenMtto, mtto_UnidadDetalle>>)query; ?

    3. Te pongo ejemplos de lo que pasa si lo hago de dos formas diferentes pero usándolos desde la ventana Orígenes de Datos:

    en el primero en el query pongo el Include, pero mtto_UnidadDetalle siempre es null:

    Y si solo pongo retornar el ObjectContext con el Include, para el mismo registro del ejemplo anterior, mtto_UnidadDetalle si tiene la información correspondiente:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni, string _tipomantenimiento)
    {
        return this.ObjectContext.mtto_OrdenMtto.Include("mtto_UnidadDetalle").Where(o => o.IDUni.Equals(_iduni));
    }

    Porqué?


    cyndyrdz

    viernes, 28 de noviembre de 2014 15:35
  • Esta parece ser mi opción, en realidad mi query debe regresar un solo registro pues una Unidad solo puede tener una Orden de Mtto abierta:

    public IQueryable<mtto_OrdenMtto> GetMtto_OrdenMttoAbiertaxIDUni(string _iduni, string _tipomantenimiento)
    {
        ObjectQuery<mtto_OrdenMtto> ordenes = this.ObjectContext.mtto_OrdenMtto;
        ObjectSet<mtto_OrdenMttoEstatus> Estatus = this.ObjectContext.mtto_OrdenMttoEstatus;
        ObjectSet<mtto_UnidadDetalle> unidades = this.ObjectContext.mtto_UnidadDetalle;
        ObjectSet<mtto_TipoMantenimiento> tipomttos = this.ObjectContext.mtto_TipoMantenimiento;
    
        mtto_OrdenMtto varquery;
    
        varquery =
                (from o in ordenes
                    join e in Estatus on o.ID equals e.IDOrdenMtto
                    join u in unidades on o.IDUni equals u.IDUni
                    join t in tipomttos on u.IDTipoEquipo equals t.IDTipoEquipo
                    where o.IDUni.Equals(_iduni)
                        && !Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA") && oe.IDOrdenMtto == o.ID)
                    select o).Distinct().FirstOrDefault();
    
        return this.ObjectContext.mtto_OrdenMtto.Include("mtto_UnidadDetalle").Where(o => o.ID.Equals(varquery.ID));
    }
    Y así si me incluye mtto_UnidadDetalle en el resultado, no sé si sea lo correcto, pero sí está funcionando bien....


    cyndyrdz

    viernes, 28 de noviembre de 2014 22:34
  • Hola Cynthia.

    Si lo que necesitas es regresar un objeto con algunas propiedades. en el new seleccionas las propiedades que necesitas. 

    Te escribo el código de mi prueba unitaria. en el caso que necesites los dos objetos.

    public static IEnumerable<Tuple<A, B>> Example()
            {
                var a = new List<A> { 
                 new A{ID=1},
                 new A{ID=2},
                 new A{ID=3}
                };
                var b = new List<B> { 
                    new B{ID=1,nombre="ALDO "},
                    new B{ID=2,nombre="eduardo"},
                    new B{ID=3,nombre="flores"}
                };
                var res = from consulta in a
                          join consultab in b on consulta.ID equals consultab.ID
                          select new Tuple<A, B>(consulta, consultab);
                return res;
            }

    Saludos

    Aldo Flores Reyes

    @alduar

    lunes, 1 de diciembre de 2014 9:11
  • Según una consulta que hice en otro foro, el problema se origina cuando hago JOIN con otras tablas, es cuando se pierde el "Include": http://stackoverflow.com/questions/27160428/includemytable-in-linq-to-entities-in-silverlight/27167144#27167144

    Así que la opción que implementé y agregué en mi comentario #6 en este post, que es primero obtener la orden que busco (haciendo los joins y filtros necesarios) y luego enviar el ObjectContext con el Include filtrando para esa orden, es la implementación correcta.


    cyndyrdz

    martes, 2 de diciembre de 2014 16:05