none
como saber si un IQueryable es vacio RRS feed

  • Pregunta

  • hola de nuevo a todos!!

    segun lo aprendido por aqui ya me manejo algo con el RIA service pero bien tengo este metodo

    public IQueryable<t_clientes> GetClientePorCifNif(string CifNif){...}

    y bien mi duda es que cuando yo busco un cliente con su cifNif y esta en mi bd todo genial pero si este no esta el IQueryable logicamente está vacio y por consiguiente pues no le puedo permitir entrar al portal y le mostrare una childWindow con el error, pero como puedo saber si esta vacio el IQueryabl. He probado con el FirstOrDefault() pero nose porque la condicion if(...)else no me la ejecuta bien. Alguna posible solución?

     

    gracias y un saludo

    miércoles, 15 de septiembre de 2010 9:40

Respuestas

  • Hola ferny

    Me falto escribir el LoadOperation en el codigo, que es el que crea el evento, te pongo la clase de como quedaria:

     public partial class MainPage : UserControl
      {
        Silverlight_RIA.Web.Services.DomainService1 c = new Web.Services.DomainService1();
    
        public MainPage()
        {
          //InformacionClienteContext
          InitializeComponent();        
        }
    
        private void _btAceptar_Click(object sender, RoutedEventArgs e)
        {
          // Invocamos al metodo GerClientePorCifNif del RIA service para comprobar que existe el cliente
          System.ServiceModel.DomainServices.Client.LoadOperation loadOperation = c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
    
          // asociar evento de ejecucion asincrona de la consulta (por si se desea tratar los datos)
          loadOperation.Completed += new EventHandler(loadOperation_Completed); 
        }
    
        /// <summary>
        /// Evento de carga de la consulta
        /// </summary>
        /// <param name="sender">objeto remitente</param>
        /// <param name="e">argumentos del evento</param>
        void loadOperation_Completed(object sender, EventArgs e)
        {
          var entity = ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities;
    
          if (entity.Count() > 0)
          {
            //El cliente existe;
            RellenarClientePortal();
            NavigationService.Navigate(new Uri("/Views/PortalReposiciones.xaml", UriKind.Relative));
          }
          else
          {
            ChildWindow errorWin = new VentanaError("Error de programa", "Se ha producido el siguiente error: " + ex.Message);
            errorWin.Show();
          }
        }
      }
    

    No la he probado, pero esto si que deberia de funcionar.

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta ferny6 miércoles, 22 de septiembre de 2010 8:20
    martes, 21 de septiembre de 2010 18:59
  • hola David y gracias por el esfuerzo en intentar comprenderme jejej. te Explico desde el principio:

    Tengo una aplicacion en Silverlight 4.0(hasta ai todo bien) y para comunicarme con los datos utilizao RIA Servide de WCF(el nimbre del servicio es InformacionClienteService.cs)  donde t_cliente es el nombre de la tabla de mi base de datos y bien una vez creado me hago mi metodo para que me busque un clietne en concreto:

    public IQueryable<t_clientes> GetClientePorCifNif(string CifNif){...}
    

    posteriormente desde un formulario .xaml hago uso de ese metodo:

    Donde el objeto "c", (cuyo nombre estoy contigo es poco ortodoxo pero como estoy haciendo prubeas y borrando y volviendo a escribir pues opto por hacerlo asi y luego revisar y renombrar) es del tipo InformacionClienteContext

    InformacionClienteContext c =  new InformacionClienteContext();

    c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
        
    if
     (c.t_clientes.Count() > 0)
    {
     c.t_clientes.First().nombre = ClientePortal.Nombre;
     MessageBox.Show("cliente: "
     + c.t_clientes.First().nombre);
     NavigationService.Navigate(new
     Uri("/Views/PortalReposiciones.xaml"
    , UriKind.Relative));
    }
    else
    
    {
     ChildWindow errorWin = new
     VentanaError("Control de Acceso Portal Reposiciones WEB"
    , "NO SE PUEDE ACCEDER AL PORTAL, el CIF del Cliente insertado o Número de Factura NO SON VÁLIDOS, por favor pongase en contacto con su agente comercial, disculpe las molestias. "
    );
     errorWin.Show();
    }
    


    pues bien lo que yo quiero hacer es:

    en primer lugar que si el cliente no existe saber como tratar a la varible "c" o quien corresponda para ver si es null.

    despues si existe leer el objeto con todos los datos del cliente y guardarlos en una clase statica (ClientePortal.cs) que tengo para poder usarlos posteriormente.

     

    pero nose si y seguramente no comprenda my bien la forma de manejo de estos objetos y la manera de programar en SIlverlight de momento es muy diferente a lo que andaba haciendo, por cierto soy recien titulado y con poca exriencia pero con muchas ganas

     

    gracias una vez mas

    • Marcado como respuesta ferny6 jueves, 16 de septiembre de 2010 10:56
    miércoles, 15 de septiembre de 2010 18:05

Todas las respuestas

  • Hola ferny.

    Si es nulo esta claro, pero la funcion si hace uso de RIA te creara uno sin elementos, de modo que puedes hacer uso del metodo extensor de linq 'count()': algo como esto

    IQueryable<t_clientes> clientes = GetClientePorCifNif(string CifNif);
    if (clientes.count() == 0) lo que quieras hacer....
    

     

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 15 de septiembre de 2010 10:19
  • gracias David, esa opción ya la he probado, pero siempre me resuelve la comprobacion a true. resulta que la comprobacion la estoy haciendo en el formulario de Login y no puedo crear variables de tipo IQueryable<t_cliente>, lo que yo hago es esto:

     

    c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
            
    if (c.t_clientes.Count() > 0)
    {
      c.t_clientes.First().nombre = ClientePortal.Nombre;
      MessageBox.Show("cliente: " + c.t_clientes.First().nombre);
      NavigationService.Navigate(new Uri("/Views/PortalReposiciones.xaml", UriKind.Relative));
    }
    else
    {
      ChildWindow errorWin = new VentanaError("Control de Acceso Portal Reposiciones WEB", "NO SE PUEDE ACCEDER AL PORTAL, el CIF del Cliente insertado o Número de Factura NO SON VÁLIDOS, por favor pongase en contacto con su agente comercial, disculpe las molestias. ");
      errorWin.Show();
    }
    

    el metodo del Load me devuelve bien el cliente por su nif porque solo entra con un nif correcto y cualquier otro no, pero luego cuado me guardo la info de mi cliente en una clase estatica para usar por toda la aplicacion no me guarda, es decir, c.t_clientes.First().nombre es vacio y me estoy volviendo loco xD.

     

     

    miércoles, 15 de septiembre de 2010 11:05
  • Hola ferny.

    Exactamente, has puesto la comparacion pero hace falta saber que es 'c' (un nombre un poco corto para un objeto, no es una buena practica ;), y como esta implementado t_clientes ¿que tipo de objeto es?, supongo que es algun tipo de coleccion.

    Lo que si te puedo decir es que si en el if estableces un punto de interrupcion y visualizas la variable c.t_clientes.First() y no contiene un supuesto t_cliente, es por que nunca se ha insertado o por que se ha borrado.

    ¿Como asignas las propiedades a t_cliente(por decir un nombre)?, debes de tener en cuenta que en el IQuerytable es un objeto optimizado para la consulta y deberias de realizar un .select sobre el para obtener un IEnumerable<> y guardarlo o hacer lo que quieras con el.


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 15 de septiembre de 2010 16:18
  • hola David y gracias por el esfuerzo en intentar comprenderme jejej. te Explico desde el principio:

    Tengo una aplicacion en Silverlight 4.0(hasta ai todo bien) y para comunicarme con los datos utilizao RIA Servide de WCF(el nimbre del servicio es InformacionClienteService.cs)  donde t_cliente es el nombre de la tabla de mi base de datos y bien una vez creado me hago mi metodo para que me busque un clietne en concreto:

    public IQueryable<t_clientes> GetClientePorCifNif(string CifNif){...}
    

    posteriormente desde un formulario .xaml hago uso de ese metodo:

    Donde el objeto "c", (cuyo nombre estoy contigo es poco ortodoxo pero como estoy haciendo prubeas y borrando y volviendo a escribir pues opto por hacerlo asi y luego revisar y renombrar) es del tipo InformacionClienteContext

    InformacionClienteContext c =  new InformacionClienteContext();

    c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
        
    if
     (c.t_clientes.Count() > 0)
    {
     c.t_clientes.First().nombre = ClientePortal.Nombre;
     MessageBox.Show("cliente: "
     + c.t_clientes.First().nombre);
     NavigationService.Navigate(new
     Uri("/Views/PortalReposiciones.xaml"
    , UriKind.Relative));
    }
    else
    
    {
     ChildWindow errorWin = new
     VentanaError("Control de Acceso Portal Reposiciones WEB"
    , "NO SE PUEDE ACCEDER AL PORTAL, el CIF del Cliente insertado o Número de Factura NO SON VÁLIDOS, por favor pongase en contacto con su agente comercial, disculpe las molestias. "
    );
     errorWin.Show();
    }
    


    pues bien lo que yo quiero hacer es:

    en primer lugar que si el cliente no existe saber como tratar a la varible "c" o quien corresponda para ver si es null.

    despues si existe leer el objeto con todos los datos del cliente y guardarlos en una clase statica (ClientePortal.cs) que tengo para poder usarlos posteriormente.

     

    pero nose si y seguramente no comprenda my bien la forma de manejo de estos objetos y la manera de programar en SIlverlight de momento es muy diferente a lo que andaba haciendo, por cierto soy recien titulado y con poca exriencia pero con muchas ganas

     

    gracias una vez mas

    • Marcado como respuesta ferny6 jueves, 16 de septiembre de 2010 10:56
    miércoles, 15 de septiembre de 2010 18:05
  • ya solucione el problema gracias por la ayuda prestada xD.

     

    Gracias

    jueves, 16 de septiembre de 2010 10:55
  • Hola ferny.

    OK, no he tenido tiempo de responder hasta ahora, asi que contesto para todos aquellos que tengan la misma duda.

    RIA services hay que tratarlos de igual forma que WCF, las operaciones internas son identicas en cuanto al uso del servicio, me explico.

    Desde silverlight no se pueden realizar llamadas sincronas a servicios web, WCF y por tanto a RIA services, todas las llamadas son asincronas (algo logico). Pues bien, en el codigo que has puesto, al hacer 'c.Load()' estas llamando al servicio para que cargue los datos, pero no los carga inmediatamente, si no que realiza la llamada asincronamente.

    de modeo que para poder obtener los datos asincronamente hay que hacerlo de forma parecida a WCF, algo como esto:

    InformacionClienteContext c = new InformacionClienteContext();
    // asociar evento de ejecucion asincrona de la consulta
    c.Completed += new EventHandler(loadOperation_Completed);
    

    y luego se implementa el evento que sera llamado cuando los datos se obtengan

    /// <summary>
    /// Evento de carga de la consulta
    /// </summary>
    /// <param name="sender">objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    void loadOperation_Completed(object sender, EventArgs e)
    {
      var first = ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities.First();
    }
    

    y sera en este evento donde se pueden tratar los datos obtenidos del servicio RIA.

    Obviamente el evento se puede implementar mediante un metodo anonimo como la siguiente forma (para simplificar)

    InformacionClienteContext c = new InformacionClienteContext();
    // asociar evento de ejecucion asincrona de la consulta
    c.Completed += delegate(object sender, EventArgs e)
    {
      var first = ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities.First();
    };
    

    En definitiva, hay que pensar que todos los servicios desde silverlight son llamados asincronamente siempre.

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    jueves, 16 de septiembre de 2010 11:09
  • Todo mucho mas clarito, de verdad.

    Creo que con esto me has aclarado una duda que tengo que a continuación te explico:

    yo cuando hago c.Load() del metodo que sea, los datos llegan de manera asincrona y entonces yo como tengo asociada la acción de traerme los datos cuando pulso el boton Aceptar de mi formulario, la primera vez que yo relleno el campo usuario y pulso el boton siempre me sale el mensaje de usuario no valido ya que como en un primer momento no obtuve los datos pues no existe obviamente, y cuando vuelvo a pulsar otra vez pues ya si que le permite el acceso puesto que la llamada se ralizo. Pienso despues de leer tu respuesta anterior que se debera a que la llamada es asincrona. Existe alguna manera de solucionarlo, que solo pulsandole una vez acceda.

    Se me ocurre que cuando cambien el contenido del textBox se invoque al c.Load() y asi cuando se haga click en el boton ya esten los datos en el cliente. bien?

     

    mil gracias de nuevo

    jueves, 16 de septiembre de 2010 19:08
  • Hola ferny.

    La forma correcta de hacer esto seria la siguiente:

    realizas la llamada asincrona y mientras tanto muestras una imagen de 'cargando' o verificando credenciales, luego, en la funcion callback(evento asincrono de carga) verificas el usuario, quitas la imagen y realaizas la logica para ir a la seccion acceso correcto o acceso incorrecto.

    de modo que cuando pulses el boton, tan solo tienes que mostrar una imagen de cargando y en la funcion callback, eliminar la imagen, realizar la comprobacion y el acceso.

    si teienes problema con esto comentalo.


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    viernes, 17 de septiembre de 2010 9:00
  • Hola david!! me parece mejor idea la manera que tu comentas, si no te importa podrías indicarme como hacerlo, porque nose como usar el callBack (AsyncCallBack) ni asociarlo al metodo correspondiente. Puedes si quieres adaptar el codigo que puse en los mensajes anteriores. Seria de gran ayuda

     

    Un saludo

    lunes, 20 de septiembre de 2010 8:20
  • Hola ferny.

    Ahora mismo no tengo ningun proyecto montado, asi que te lo escribo aproximadamente con tu codigo (no esta verificada la sintaxis):

    //--------------------------------------------------------
    // Codigo a insertar donde mejor convenga 
    // por ejemplo en el constructor para mantener el contexto y su evento en variables miembro
    InformacionClienteContext c = new InformacionClienteContext();
    // asociar evento de ejecucion asincrona de la consulta
    c.Completed += new EventHandler(loadOperation_Completed);
    
    
    //--------------------------------------------------------
    // codigo a insertar en el evento del boton aceptar
    c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
    // TODO: hacer visible una imagen
    
    //--------------------------------------------------------
    // Evento ocurrido al cargarse los datos
    /// <summary>
    /// Evento de carga de la consulta
    /// </summary>
    /// <param name="sender">objeto remitente</param>
    /// <param name="e">argumentos del evento</param>
    void loadOperation_Completed(object sender, EventArgs e)
    {
      var entities = ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities;
    
      if (entities.Count() > 0)
      {
        // tu codigo era algo asi:
        c.t_clientes.First().nombre = ClientePortal.Nombre;
        MessageBox.Show("cliente: "
        + c.t_clientes.First().nombre);
        NavigationService.Navigate(new
        Uri("/Views/PortalReposiciones.xaml"
        , UriKind.Relative))
      }
      else
      {
        // TODO: insertar el codigo de error o de NO acceso del usuario
      }
    
      // TODO: hacer invisible la imagen, en cualquier caso, la imagen se oculta
    }
    
    
    

    Mas o menos seria algo asi, si tienes algun problema en la implantacion comentalo.

     

     

     

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    lunes, 20 de septiembre de 2010 11:56
  • Hola David! estoy intentando hacer lo que me dijiste hace unos dias pero no puedo asociar el evento Completed a mi InformacionClienteContext
    martes, 21 de septiembre de 2010 17:23
  • Hola ferny.

    ¿InformacionClienteContext de que tipo es?, ponme el codigo que tienes actualmente a ver si damos con la solucion.


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    martes, 21 de septiembre de 2010 18:12
  •  private void _btAceptar_Click(object sender, RoutedEventArgs e)
        {
          bool error = false;<br/>
                InformacionClienteContext c = new InformacionClienteContext();<br/>
    <br/>
                if (_tbCliente.Text != "")
          {
            try
            {
              // Invocamos al metodo GerClientePorCifNif del RIA service para comprobar que existe el cliente
              c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
    
              if (c.t_clientes.Count() > 0)
              {
                //El cliente existe;
                RellenarClientePortal();
                NavigationService.Navigate(new Uri("/Views/PortalReposiciones.xaml", UriKind.Relative));
              }
              else
              {
                error = true;
              }
            }
            catch (Exception ex)
            {
              ChildWindow errorWin = new VentanaError("Error de programa", "Se ha producido el siguiente error: " + ex.Message);
              errorWin.Show();
            }
          }
    
          if (_tbCliente.Text == "" || error)
          {
              ChildWindow errorWin = new VentanaError("Control de Acceso Portal Reposiciones WEB", "NO SE PUEDE ACCEDER AL PORTAL, el CIF del Cliente insertado o Número de Factura NO SON VÁLIDOS, por favor pongase en contacto con su agente comercial, disculpe las molestias. ");
              errorWin.Show();
          }
        }
    
    Te comenteo que InformacionClienteContext es el nombre que le doy al servios de RIA que he creado. Creo el modelo con la tabla de clientes y luego creo el DomainService cuyo nombre le pongo InformacionClienteService pero como sabes se hace uso de el mediante el InformacionClienteService.

     

     

     

    martes, 21 de septiembre de 2010 18:21
  • Hola ferny

    Me falto escribir el LoadOperation en el codigo, que es el que crea el evento, te pongo la clase de como quedaria:

     public partial class MainPage : UserControl
      {
        Silverlight_RIA.Web.Services.DomainService1 c = new Web.Services.DomainService1();
    
        public MainPage()
        {
          //InformacionClienteContext
          InitializeComponent();        
        }
    
        private void _btAceptar_Click(object sender, RoutedEventArgs e)
        {
          // Invocamos al metodo GerClientePorCifNif del RIA service para comprobar que existe el cliente
          System.ServiceModel.DomainServices.Client.LoadOperation loadOperation = c.Load(c.GetClientePorCifNifQuery(_tbCliente.Text));
    
          // asociar evento de ejecucion asincrona de la consulta (por si se desea tratar los datos)
          loadOperation.Completed += new EventHandler(loadOperation_Completed); 
        }
    
        /// <summary>
        /// Evento de carga de la consulta
        /// </summary>
        /// <param name="sender">objeto remitente</param>
        /// <param name="e">argumentos del evento</param>
        void loadOperation_Completed(object sender, EventArgs e)
        {
          var entity = ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities;
    
          if (entity.Count() > 0)
          {
            //El cliente existe;
            RellenarClientePortal();
            NavigationService.Navigate(new Uri("/Views/PortalReposiciones.xaml", UriKind.Relative));
          }
          else
          {
            ChildWindow errorWin = new VentanaError("Error de programa", "Se ha producido el siguiente error: " + ex.Message);
            errorWin.Show();
          }
        }
      }
    

    No la he probado, pero esto si que deberia de funcionar.

     


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta ferny6 miércoles, 22 de septiembre de 2010 8:20
    martes, 21 de septiembre de 2010 18:59
  • Mil gracias David, funciona perfectamente y te has portado un monton, gracias de nuevo. Solo tengo una preguntilla, la variable entity del LoadOperation_Completed supongo que se correspondera con c.t_clientes y se puede utilizar con tal, no?

     

    Un saludo

    miércoles, 22 de septiembre de 2010 8:23
  • Hola ferny.

    esa variable es lo que te retorna GetClientePorNifQuery, que si corresponde en tu caso(supongo que si) lo puedes meter en c.t_clientes.


    Saludos
    David González
    MCP.
    Visita mi Blog en: http://www.dgzornoza.com/
    miércoles, 22 de septiembre de 2010 12:10
  • Que pena

    David

    Pero estuve probando tu código y no funciona me sale un error en el EventHandler

    Seria posible que lo puedas corregir

    Gracias

     

    viernes, 26 de noviembre de 2010 19:26
  • Hola Luis.

    ¿que error te sale? ¿te compila o es un error en ejecucion?


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    viernes, 26 de noviembre de 2010 20:15
  • Que pena David el error era mio

    Gracias,

     

    Pero tengo una pregunto como hago para Insertar,Actualizar y Borrar, con los RIA Service

     

    Gracias,

    viernes, 26 de noviembre de 2010 20:43
  • Hola de nuevo.

    En estos 2 post se habla mas de ello (intenta dejar las preguntas en los post abiertos para no resucitar temas antiguos).

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/66b1d2d8-1a21-432d-8781-32b9ddd72eb7

    http://social.msdn.microsoft.com/Forums/es-ES/wpfes/thread/1a23483d-5812-494b-b04c-8b6c80ca0228

     

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    lunes, 29 de noviembre de 2010 19:54
  • Hola

    David

    ((System.ServiceModel.DomainServices.Client.LoadOperation)sender).Entities.First();
    El miembro First no sale en la ayuda del Intelizise

    Gracias

    lunes, 29 de noviembre de 2010 21:40
  • Hola Luis.

    El metodo First(), es un metodo extensor de LinQ, ¿no sale este solo o no sale ningun metodo extensor de LinQ?, ya que si no sale ninguno es posible que falte insertar la directiva: 

    using System.Linq

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    martes, 30 de noviembre de 2010 18:36