none
Apontamento de horas RRS feed

  • Pergunta

  • Eu preciso criar uma função booleana para contar o número de linhas de uma consulta onde entram como parâmetros o código do consultor, a data/Hora do início do serviço e a data/Hora do 
    fim do serviço.
    Essa função deverá comparar os três parâmetros com os campos CST_CODIGO, AGE_DATAHORAINICIAL e AGE_DATAHORAFINAL que estão no banco de dados no formato longo.
    A consulta verificará se o apontamento já existe.

    Caso sim, retorna como false (para que o sistema avise que já existe apontamento para o consultor nesse horário informando que não é possível apontar.
    Se não existir, retorna como true (para o sistema fazer a inserção desse apontamento).
    Lembrando que se o valor de vInicio e vFim estiverem dentro do intervalo de qualquer apontamento para a data e o msm consultor, não deve ser permitido o apontamento em duplicidade.

    int vCons = Convert.ToInt32(vConsultor.totext);
    DateTime _dataPesquisaInicial = DateTime.Parse(string.Format("{0} {1}", vDate, vInicio));
    DateTime _dataPesquisaFinal   = DateTime.Parse(string.Format("{0} {1}", vDate, vFim));
                   var result = from ap in ef.Consultores_Agenda
                             where ap.CST_CODIGO == vCons
                             & (ap.AGE_DATAHORAINICIAL.Ticks >= _dataPesquisaInicial.Ticks
                             & ap.AGE_DATAHORAFINAL.Ticks <= _dataPesquisaFinal.Ticks)                         
                             select new { ap.AGE_DATAHORAINICIAL, ap.AGE_DATAHORAFINAL, ap.CST_CODIGO };

    int SelectedRow = result.count();
    if (SelectedRow > 0)
    return false
    else
    return true
    end;

    Esse código com o Ticks até funciona, porém não consigo retornar a quantidade de linhas retornadas pela consulta.
    Também não tenho muita certeza se a consulta está trazendo todos os dados do intervalo corretamente.
    quinta-feira, 19 de abril de 2012 04:49

Respostas

  • Fernando.

    Eu fiz uma alteração no banco e transformei os campos de horas em time mesmo.

    depois eu fiz a seguinte implementação:

                     private bool Valida_Apontamento()
            {
            TimeSpan _dataPesquisaInicial = System.TimeSpan.Parse(Tb_HoraInicial.Text);
            TimeSpan _dataPesquisaFinal = System.TimeSpan.Parse(Tb_HoraFinal.Text);
            int vCons = Convert.ToInt32(Tb_Consultor.Text);
            int Qtde = 0;
            int Linhas = 0;
            var result = from ap in ef.Consultores_Agenda
                              where ap.AGE_DATA == Tb_Data.Text 
                              && ap.CST_CODIGO == vCons
                         select new { ap.AGE_HHINICIAL, ap.AGE_HHFINAL, ap.CST_CODIGO };
             
            Qtde = result.Count();

            if (Qtde > 0)
            {
                var result02 = from ap in result
                               where
                                     (ap.AGE_HHINICIAL <= _dataPesquisaInicial &&
                                     ap.AGE_HHFINAL >= _dataPesquisaFinal) ||
                                     (ap.AGE_HHINICIAL <= _dataPesquisaFinal &&
                                     ap.AGE_HHINICIAL >= _dataPesquisaInicial) ||
                                      (ap.AGE_HHFINAL <= _dataPesquisaFinal &&
                                     ap.AGE_HHFINAL >= _dataPesquisaInicial)
                               select ap;
                Linhas = result02.Count();
                if (Linhas > 0)
                {
                    Lb_Op.Text = "Apontamento já existente para a data!";
                    return false;
                }
                else
                {
                    Lb_Op.Text = "Apontar normalmente";
                    return true;
                }
            }
            else
            {
                Lb_Op.Text = "Apontar normalmente";
                return true;
            }        
        }

    Essa função booleana seria para validação ou não do apontamento retornando true para apontar normalmente ou false se existisse um apontamento.

    a lógica foi a seguinte: primeiro filtrei apenas o consultor e a data (o select traria apenas os que tem apontamentos para a data) se ele não tem nenhum apontamento, nem executa o segundo select.

    Depois que o primeiro select retorna os apontamentos, faço um segundo select para comparar as possibilidades do apontamento estar dentro do intervalo de algum apontamento já efetuado.

    Deu certo em todos os casos, observando que houve a necessidade de colocar um parênteses dentro do where do segundo select.

    Dê uma olhada no código e me fale o que achou.

    Abs.

    sexta-feira, 20 de abril de 2012 21:40

Todas as Respostas

  • Fernando,

    Como assim você nao está conseguindo retornar a quantidade de linhas? Você pegou o resultado com o Count, por quê você simplesmente nao retorna esse valor (ou propaga ele através de um parâmetro out)?

    Além disso, tem alguma razao para você estar utilizando o operador & ao invés do &&? Acredito que nesse seu caso nao vai fazer muita diferenca, mas, se você utilizar o && vai evitar algumas checagens desnecessarias... (http://msdn.microsoft.com/en-us/library/2a723cdk.aspx)


    André Alves de Lima
    Microsoft MVP - Client App Dev
    Visite o meu site: http://www.andrealveslima.com.br
    Me siga no Twitter: @andrealveslima

    quinta-feira, 19 de abril de 2012 10:13
    Moderador
  • Olá Fernando,

    Esse comando aqui deve estar em letra maiuscula:

    int SelectedRow = result.Count();

    Outro ponto, vc fez referência ao namespace System.Linq?

    Vc esta com algum erro de sintaxe sendo apontado pelo Visual Studio?

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    quinta-feira, 19 de abril de 2012 11:41
    Moderador
  • André e Fernando

    Eu fiz a alteração no código inserindo && ao invés de &, além de ter o namespace System.Linq declarado.

    Porém ao executar o código com as alterações abaixo, aparece o seguinte erro: The specified type member 'Ticks' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. 

    DateTime _dataPesquisaInicial = DateTime.Parse(string.Format("{0} {1}", Tb_Data.Text, Tb_HoraInicial.Text));
            DateTime _dataPesquisaFinal = DateTime.Parse(string.Format("{0} {1}", Tb_Data.Text, Tb_HoraFinal.Text));
            int vCons = Convert.ToInt32(Tb_Consultor.Text);
            var result = from ap in ef.Consultores_Agenda
                              where (ap.AGE_HHINICIAL.Ticks >= _dataPesquisaInicial.Ticks
                              || ap.AGE_HHFINAL.Ticks <= _dataPesquisaFinal.Ticks)
                              && ap.CST_CODIGO == vCons
                              select new { ap.AGE_HHINICIAL, ap.AGE_HHFINAL, ap.CST_CODIGO };
                int SelectedRows = result.Count();

    Aparentemente o linq não reconhece o comando tick. Há alguma outra forma de fazer?

    quinta-feira, 19 de abril de 2012 12:37
  • Olá Fernando,

    Vc tentou comparar os datetimes desta forma?

    DateTime _dataPesquisaInicial = DateTime.Parse(string.Format("{0} {1}", Tb_Data.Text, Tb_HoraInicial.Text));
            DateTime _dataPesquisaFinal = DateTime.Parse(string.Format("{0} {1}", Tb_Data.Text, Tb_HoraFinal.Text));
            int vCons = Convert.ToInt32(Tb_Consultor.Text);
            var result = from ap in ef.Consultores_Agenda
                              where (ap.AGE_HHINICIAL >= _dataPesquisaInicial
                              || ap.AGE_HHFINAL <= _dataPesquisaFinal)
                              && ap.CST_CODIGO == vCons
                              select new { ap.AGE_HHINICIAL, ap.AGE_HHFINAL, ap.CST_CODIGO };
                int SelectedRows = result.Count();

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    quinta-feira, 19 de abril de 2012 12:54
    Moderador
  • Sim, porém ele aparentemente não está trazendo corretamente os dados.

    Por exemplo: se eu estiver tentando apontar o consultor 8 no dia 09/04/2012 das 09:00 as 11:00 e tiver um apontamento para o mesmo consultor das 09:00 as 18:00 no mesmo dia, ele traz corretamente.

    Mas  se eu tentar apontar algo do tipo 10:00 as 13:00 para o mesmo consultor e no mesmo dia, ele retorna como se não tivesse nenhum apontamento.

    Talvez seja algum erro no where mas ainda não consegui identificar.

    O ideal seria que ele retornasse qualquer valor dentro do intervalo já apontado para a data e para o consultor.

    quinta-feira, 19 de abril de 2012 14:18
  • Olá Fernando,

    No seu filtro, o valor que vc esta passando paraCST_CODIGO realmente é o q esta cadastrado?

    Me parece que as datas estão certas.

    []s!



    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    quinta-feira, 19 de abril de 2012 18:20
    Moderador
  • Está correto sim. CST_CODIGO é uma chave do tipo int.
    quinta-feira, 19 de abril de 2012 19:53
  • Olá Fernando,

    Acredito que vc terá de dividir sua query em dois blocos: um que execute no servidor para reter os dados, e uma segunda query para filtrar os períodos e utilizar métodos como TimeOfDay (que não são suportados pelo Entity Framework.

    Segue o exemplo:

                var result01 = (from ap in agendas
                                where
                                     ap.AGE_HHINICIAL.Day == _dataPesquisaInicial.Day &&
                                     ap.AGE_HHINICIAL.Month == _dataPesquisaInicial.Month &&
                                     ap.AGE_HHINICIAL.Year == _dataPesquisaInicial.Year &&
                                     ap.CST_CODIGO == vCons
                                select ap).ToList();
    
                if (result01.Count > 0)
                {
                    var result02 = from ap in result01
                                   where
                                         (ap.AGE_HHINICIAL.TimeOfDay <= _dataPesquisaInicial.TimeOfDay &&
                                         ap.AGE_HHFINAL.TimeOfDay >= _dataPesquisaFinal.TimeOfDay) ||
                                         (ap.AGE_HHINICIAL.TimeOfDay <= _dataPesquisaFinal.TimeOfDay &&
                                         ap.AGE_HHINICIAL.TimeOfDay >= _dataPesquisaInicial.TimeOfDay) ||
                                          (ap.AGE_HHFINAL.TimeOfDay <= _dataPesquisaFinal.TimeOfDay &&
                                         ap.AGE_HHFINAL.TimeOfDay >= _dataPesquisaInicial.TimeOfDay)
                                   select ap;
                }

    O meu teste foi feito assim:

            public class Agenda
            {
                public DateTime AGE_HHINICIAL { get; set; }
                public DateTime AGE_HHFINAL { get; set; }
                public int CST_CODIGO { get; set; }
            }
    
            static void Main(string[] args)
            {
                int vCons = 1;
                DateTime _dataPesquisaInicial = new DateTime(2012, 04, 09, 9, 00, 00);
                DateTime _dataPesquisaFinal = new DateTime(2012, 04, 09, 18, 00, 00);
    
    
                List<Agenda> agendas = new List<Agenda>();
                agendas.Add(new Agenda() { CST_CODIGO = vCons, AGE_HHINICIAL = new DateTime(2012, 04, 09, 09, 00, 00), AGE_HHFINAL = new DateTime(2012, 04, 09, 18, 00, 00) });
    
    
                var result01 = (from ap in agendas
                                where
                                     ap.AGE_HHINICIAL.Day == _dataPesquisaInicial.Day &&
                                     ap.AGE_HHINICIAL.Month == _dataPesquisaInicial.Month &&
                                     ap.AGE_HHINICIAL.Year == _dataPesquisaInicial.Year &&
                                     ap.CST_CODIGO == vCons
                                select ap).ToList();
    
                if (result01.Count > 0)
                {
                    var result02 = from ap in result01
                                   where
                                         (ap.AGE_HHINICIAL.TimeOfDay <= _dataPesquisaInicial.TimeOfDay &&
                                         ap.AGE_HHFINAL.TimeOfDay >= _dataPesquisaFinal.TimeOfDay) ||
                                         (ap.AGE_HHINICIAL.TimeOfDay <= _dataPesquisaFinal.TimeOfDay &&
                                         ap.AGE_HHINICIAL.TimeOfDay >= _dataPesquisaInicial.TimeOfDay) ||
                                          (ap.AGE_HHFINAL.TimeOfDay <= _dataPesquisaFinal.TimeOfDay &&
                                         ap.AGE_HHFINAL.TimeOfDay >= _dataPesquisaInicial.TimeOfDay)
                                   select ap;
                }

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 20 de abril de 2012 13:01
    Moderador
  • Fernando.

    Nós pensamos na mesma solução.

    Vou testar baseado no seu código e depois eu posto o resultado, ok?

    valeu.

    sexta-feira, 20 de abril de 2012 20:04
  • Fernando.

    Eu fiz uma alteração no banco e transformei os campos de horas em time mesmo.

    depois eu fiz a seguinte implementação:

                     private bool Valida_Apontamento()
            {
            TimeSpan _dataPesquisaInicial = System.TimeSpan.Parse(Tb_HoraInicial.Text);
            TimeSpan _dataPesquisaFinal = System.TimeSpan.Parse(Tb_HoraFinal.Text);
            int vCons = Convert.ToInt32(Tb_Consultor.Text);
            int Qtde = 0;
            int Linhas = 0;
            var result = from ap in ef.Consultores_Agenda
                              where ap.AGE_DATA == Tb_Data.Text 
                              && ap.CST_CODIGO == vCons
                         select new { ap.AGE_HHINICIAL, ap.AGE_HHFINAL, ap.CST_CODIGO };
             
            Qtde = result.Count();

            if (Qtde > 0)
            {
                var result02 = from ap in result
                               where
                                     (ap.AGE_HHINICIAL <= _dataPesquisaInicial &&
                                     ap.AGE_HHFINAL >= _dataPesquisaFinal) ||
                                     (ap.AGE_HHINICIAL <= _dataPesquisaFinal &&
                                     ap.AGE_HHINICIAL >= _dataPesquisaInicial) ||
                                      (ap.AGE_HHFINAL <= _dataPesquisaFinal &&
                                     ap.AGE_HHFINAL >= _dataPesquisaInicial)
                               select ap;
                Linhas = result02.Count();
                if (Linhas > 0)
                {
                    Lb_Op.Text = "Apontamento já existente para a data!";
                    return false;
                }
                else
                {
                    Lb_Op.Text = "Apontar normalmente";
                    return true;
                }
            }
            else
            {
                Lb_Op.Text = "Apontar normalmente";
                return true;
            }        
        }

    Essa função booleana seria para validação ou não do apontamento retornando true para apontar normalmente ou false se existisse um apontamento.

    a lógica foi a seguinte: primeiro filtrei apenas o consultor e a data (o select traria apenas os que tem apontamentos para a data) se ele não tem nenhum apontamento, nem executa o segundo select.

    Depois que o primeiro select retorna os apontamentos, faço um segundo select para comparar as possibilidades do apontamento estar dentro do intervalo de algum apontamento já efetuado.

    Deu certo em todos os casos, observando que houve a necessidade de colocar um parênteses dentro do where do segundo select.

    Dê uma olhada no código e me fale o que achou.

    Abs.

    sexta-feira, 20 de abril de 2012 21:40
  • Show!

    Acho que ficou mto bom :)

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sábado, 21 de abril de 2012 04:56
    Moderador
  • Valeu.

    Obrigado pelas dicas.

    Abs.

    sábado, 21 de abril de 2012 13:48