1

Mi duda es esta: Estoy usando Visual Studio 2015, y estoy programando en C# para Windows Forms, el caso que es tengo una variable que está guardada en una base de datos de SQL Server 2008, y el dato que se encuentra allí es de tipo int. Lo que deseo hacer es tomar el dato que se encuentra en la base de datos y convertirlo a tipo DateTime para poder sumarlo con otro dato que tengo previamente en mi programa para luego mostrarlo en un DGV. Si alguien me pudiese ayudar con la sintaxis necesaria, se los agradecería.

Editado:

Aclaro lo que se encuentra en la base de datos es una variable que se llama duración, y es de tipo entero, yo solo puedo realizar consultas a la base de datos, pero no puedo modificar el tipo de dato, lo que deseo hacer es que mediante una consulta hecha desde C#, pueda obtener ese dato y parsárselo si es posible a un dato de tipo datetime, para posteriormente sumarlo a otro dato del mismo tipo, esto porque me encuentro programando un control para agenda de actividades en la cual las actividades se encuentran dentro de la base de datos y cada una tiene una duración de tiempo ya asignada. Entonces el primer dato que es de tipo datetime es uno al que llamo HoraInicio, en el cual el usuario determina a qué hora comienzan sus actividades y lo que deseo hacer es que una vez teniendo la hora de inicio de la agenda, dependiendo el servicio que se agende, se calcule la duración.

Un ejemplo de lo anterior sería algo así:

servicios                    hora
junta de ejecutivos          09:00 - 11:00
Inventario                   11:00 - 11:45

Explicando lo anterior, se toma el servicio "junta de ejecutivos" y se selecciona que el servicio o la agenda empiece a las 9:00. Este dato se guarda como datetime. Ahora bien, en la base de datos ya está guardado que el servicio "junta de ejecutivos", siempre tendrá una duración de 2hrs, y lo mismo para inventario, siempre durará 45min, la suma la pienso hacer con el método datetime.addminutes() ya que la duración se encuentra en forma de minutos en la base de datos. Lo que intento hacer es que dependiendo el servicio que se haya seleccionado, también se seleccione la duración del mismo y se convierta en un dato de tipo datetime para sumarlo con el de HoraInicio, y así poder lograr lo que necesito.

El código que llevo es el siguiente:

class conexion
{
    SqlConnection con1;
    SqlCommand cmd;
    SqlDataReader dr;
    public conexion()
    {
        try
        {
            con1 = new SqlConnection("Data Source=OROCHI;Initial Catalog=AGENDAS;Persist Security Info=True;User ID=user;Password=holamundo");
            con1.Open();
        }

        catch(Exception ex)
        {
            MessageBox.Show("Error en la conexión" + ex.ToString());    
        }
 }

El proceso de conexión a la base de datos lo realizo mediante una clase, la cual se llama conexion, en la cual he realizado el llamado de todos los servicios que se encuentran en la base de datos y los agrego a un ComboBox para desplegarlos en forma de lista.

En el main intenté hacer esto, pero obviamente no funciona, y la verdad ya lo esperaba, porque no sé ni cómo hacerlo.

void duracion(int tiempo)
{
    SqlConnection con2;
    SqlCommand cmd2;
    SqlDataReader dr2;
    try
    {
        DateTime hora = DateTime.ParseExact(textBox3.Text, "HH:mm", System.Globalization.CultureInfo.InvariantCulture);
        con2 = new SqlConnection("Data Source=OROCHI;Initial Catalog=AGENDAS;Persist Security Info=True;User ID=USER;Password=Holamundo");
        con2.Open();
        cmd2 = new SqlCommand("select NB_SERVICIO, NO_BLOQUES * 5 from tablas.C_SERVICIO where NB_SERVICIO == '" + comboBox1.Text + "'", con2);
        dr2 = cmd2.ExecuteReader();
        SqlDataAdapter sda = new SqlDataAdapter("select NO_BLOQUES * 5 from tablas.C_SERVICIO where NB_SERVICIO == '" + comboBox1.Text + "'", con2);
        DataTable dt= new DataTable();
        sda.Fill(dt);
        if (dt.Rows[0][0].ToString() == "1")
        {
            DateTime horaN = hora;
            double minutos = dt.Rows;
        }
    } 
    catch(Exception ex) {
        MessageBox.Show("Error: " + ex.ToString());
    }
}

Otra parte del código que considero que puede ser de útil es esta:

private void button5_Click(object sender, EventArgs e)
{
    dataGridView2.Columns["Column2"].DefaultCellStyle.Format = "HH:mm";//<-formato de Horas/minutos
    checkedListBox1.Visible = false;
    comboBox1.Enabled = false;
    comboBox2.Enabled = false;
    textBox2.Enabled = false;
    button3.Enabled = false;
    button2.Enabled = false;
    DateTime hora = DateTime.ParseExact(textBox3.Text, "HH:mm", System.Globalization.CultureInfo.InvariantCulture);

    if (checkBox1.Checked == true)
    {  
        dataGridView2.Rows.Add(comboBox1.Text,hora);          
    }

Lo que se realiza aquí es la toma de datos de la hora de inicio de la agenda a través de un TextBox y se guarda en el tipo de dato, datetime, y luego se agrega al DGV.

Solo necesitaría saber cómo tomar la duración de la base de datos y agregarlo a la hora de inicio.

sstan
  • 16,591
  • 2
  • 21
  • 45
  • 1
    ¿Puedes compartir lo que has hecho hasta ahora? En particular, no entiendo cómo un `int` puede convertirse en un `DateTime`. Tal vez puedes explicar eso un poco mas. ¿Qué representa el campo de tipo `int`? – sstan Nov 08 '16 at 19:39
  • @sstan el `int` se puede convertir a `DateTime` solo si son `Milisegundos`, aunque mi recomendación en vez de `int` sea `Float` – JuankGlezz Nov 08 '16 at 21:05
  • 1
    @JuankGlezz: De acuerdo, pero OP debe especificar esos detalles. No podemos asumir que sea el caso. – sstan Nov 08 '16 at 21:06
  • 1
    @sstan Estoy de acuerdo contigo en ese aspecto pero solo era como darle lógica en ese aspecto de la pregunta – JuankGlezz Nov 08 '16 at 21:08
  • Muchas gracias por la notaciones, he realizado los cambios que me han solicitado y espero en verdad me puedan apoyar. Gracias – user7070220 Nov 09 '16 at 16:18
  • Hola @user7070220! Gracias por agregar mas contexto. Puede que tengamos que hacer algunas aclaraciones adicionales, pero voté para reabrir la pregunta. Asi que, si entiendo bien, el `int` en tu base de datos, en realidad no representa una fecha, sino una duración, ¿correcto? Creo que esa era la parta mas confusa de la pregunta, porque una duración no se puede convertir a una fecha, pero sí se puede agregar a una fecha. – sstan Nov 09 '16 at 16:38
  • @sstan así es mi estimado el int de la DB no representa ninguna fecha, sino como dijiste representa una duración. Y muchas gracias por lo de votar para reabrir la pregunta, para ser sincero soy bastante nuevo en la pág. – user7070220 Nov 09 '16 at 17:36
  • ¿Qué son `NB_SERVICIO` y `NO_BLOQUES`, y cuales son los tipos en la base de datos de estos 2 campos? ¿Y que significa `NO_BLOQUES * 5`, y como se relaciona a la duración? – sstan Nov 09 '16 at 18:36
  • Disculpa nuevamente por la falta de info. En NB_SERVICIO se guardan los nombres de los servicios registrados.Como se había mencionado antes acerca de "junta de ejecutivos" e "inventario" esa info se guarda allí y es de tipo varchar. Ahora NO_BLOQUES es donde se guarda la info de la duración de los servicios, es de tipo "int" solo que se guardan, aunque suene un poco redundante en bloques y para obtener la duración en minutos hay que multiplicarlos por 5.Ejemplo "junta de ejecutivos" tiene en NO_BLOQUES "24" eso se multiplica por 5 y da 120 que es la dur. final de ese servicio expresada en min. – user7070220 Nov 09 '16 at 18:48

2 Answers2

2

Aquí te dejo un modelo que te puede servir para extraer la duración de la base de datos y luego agregarlo a tu variable de tipo DateTime. Notarás que favorezco el uso de parámetros en vez de concatenar valores directamente a la cadena SQL. Te recomiendo de ir desarollando esa costumbre para evitar problemas, entre ellos la inyección SQL.

// Copiado de tu código existente que extrae la hora inicial.
DateTime horaInicio = DateTime.ParseExact(
    textBox3.Text,
    "HH:mm",
    System.Globalization.CultureInfo.InvariantCulture);

// Extraer la duración de la base de datos.
int duracionEnMinutos;
using (var conn = new SqlConnection("..."))
{
    conn.Open();

    using (var cmd = new SqlCommand(
        "select NO_BLOQUES * 5 from tablas.C_SERVICIO where NB_SERVICIO = @nbServicio",
        conn))
    {
        // Uso de parámetros en vez de concatenar directamente al SQL.
        cmd.Parameters.Add(new SqlParameter("@nbServicio", comboBox1.Text));

        duracionEnMinutos = (int)cmd.ExecuteScalar();
    }
}

// Agregar duración a la hora de inicio
DateTime horaFin = horaInicio.AddMinutes(duracionEnMinutos);

// Si deseas obtener una cadena con la hora de inicio y fin combinados así:
// 09:00 - 11:00
string intervaloFormateado =
    $"{horaInicio.ToString("HH:mm")} - {horaFin.ToString("HH:mm")}"
sstan
  • 16,591
  • 2
  • 21
  • 45
  • Muchísimas gracias mentor! sinceramente desconocía acerca de lo que mencionas acerca de inyección sql, vi el link que comentaste y es un tema bastante bueno, seguiré tu consejo. Ahora y respecto a la solución que usted propuso, fue más que excelente aunque sinceramente no entiendo muy bien como funciona, por lo que me pondré a investigar lo de los parametros y como funciona "using" ya que no había leído o visto algo de eso aún. Muchas gracias por tu tiempo y por ayudarme. Saludos – user7070220 Nov 10 '16 at 17:58
1

Creo que debes hacer varias modificaciones...


¿Qué valor recibes en textBox3? si solo recibes por ejemplo:

01:00

No te recomiendo esta manera, ya que necesitas un valor que será convertido a DateTime y 01:00 no sería un valor DateTime válido.

Para crear una variable de tipo DateTime, te sugiero cambiar tu línea de esta manera:

// El campo "textBox3.Text" tiene como valor: "09/11/2016"
// o "09/11/2016 00:00:00"
DateTime hora = DateTime.Parse(textBox3.Text);

Luego, para adicionar los minutos a la variable hora, realiza lo siguiente:

hora = hora.AddMinutes(minutos);
// Donde "minutos" es la variable de tipo double que deberías declarar por fuera de la condición "if".

La segunda consulta me parece que es redundante, no es necesaria, ya que estás obteniendo la misma información que en la primera consulta.


He modificado tu código de esta manera:

NOTA: No he probado el código, por lo que te sugiero tener una copia de tu código actual.

/// <summary>
/// Obtener DateTime con el las horas añadidas.
/// </summary>
/// <param name="tiempo">tiempo "valor del campo textBox3.Text".</param>
/// <returns>DateTime</returns>
public DateTime ObtenerFechaModificada(DateTime tiempo)
{
    SqlConnection con2;
    SqlCommand cmd2;
    SqlDataReader dr2;
    DataTable dt = new DataTable();
    double minutos = 0;
    DateTime hora = DateTime.Today();
    
    try
    {            
        // Validar si es una fecha.
        if (DateTime.TryParse(tiempo, out hora)) {
            
            // Convertir a fecha el valor del campo de texto.
            hora = DateTime.Parse(tiempo);
            
            // Consultar información.
            con2 = new SqlConnection("Data Source=OROCHI;Initial Catalog=AGENDAS;Persist Security Info=True;User ID=USER;Password=Holamundo");
            con2.Open();
            cmd2 = new SqlCommand("select NB_SERVICIO, NO_BLOQUES * 5 from tablas.C_SERVICIO where NB_SERVICIO == '" + comboBox1.Text + "'", con2);
            dr2 = cmd2.ExecuteReader();
            SqlDataAdapter sda = new SqlDataAdapter(con2);
            sda.Fill(dt);
            
            if (dt.Rows[0][0].ToString() == "1")
            {
                // Obtener los minutos.
                minutos = double.parse(dt.Rows[0]["NO_BLOQUES"].ToString());
                
                // Adicionar los minutos a la variable DateTime llamada "hora".
                hora = hora.AddMinutes(minutos);
            }
        } else {
            MessageBox.Show("No se reconoce como una fecha válida.");
            return hora;
        }
    } 
    catch (Exception ex) 
    {
        MessageBox.Show("Error: " + ex.ToString());
    }
    
    return hora;
}

Solo necesitaría saber cómo tomar la duración de la base de datos y agregarlo a la hora de inicio.

Con el código anterior, usas este método para pasarle el valor de textbox3.Text y el método te devuelve una nueva variable de tipo DateTime con la duración añadida.

Así:

textBox3.Text = 09/11/2016

El método lo convierte a DateTime quedando así: 09/11/2016 00:00:00

y suponiendo que hayas elegido la opción Inventario, la fecha resultante sería:

09/11/2016 00:45:00

Mauricio Arias Olave
  • 3,098
  • 6
  • 26
  • 55
  • 1
    Amigo muchas gracias por tu comentario, en primera agradezco el tiempo que dedicaste a revisar mi código y también por ayudarme, quiero aclarar que tu solución me marco un par de errorsillos que arregle, pero me ayudo mucho a entender lo que quería. Muchas Gracias por tu ayuda. Saludos – user7070220 Nov 10 '16 at 17:54
  • @user7070220 con todo gusto y [Bienvenido a Stack Overflow en Español](http://es.stackoverflow.com/tour) :) – Mauricio Arias Olave Nov 10 '16 at 19:03