Diskuze: Problém s ukládáním datumu do databáze

C# .NET .NET (C# a Visual Basic) Problém s ukládáním datumu do databáze American English version English version

Avatar
Maros2470
Člen
Avatar
Maros2470:

Zdravím. Mám problém. Do text boxu napíši datum např. 7.5.2014 t.j. 7.května 2014 a uložím do databáze. Po načtení z databáze do text boxu to sice je 7.5.2014 ale je to 5. července 2014. Můžete mi poradit co s tím? Děkuji za rady.

 
Odpovědět 6.11.2014 10:37
Avatar
Odpovídá na Maros2470
Michal Haňáček:

Předpokládám, že jde o zle nastavený formát data. Každopádně než text box by jsi měl asi praktičtější nějaký date picker.

Nahoru Odpovědět 6.11.2014 12:17
Každé rozhodnutí a každý krok v životě nás někam posune. Bohužel jen některé nás posouvají dopředu.
Avatar
Odpovídá na Maros2470
Nikola Sterziková (PaNika):

Před uložením do db přetypuj na datum

DateTime datumOd;
if(!DateTime.TryParse(textboxOd.Text, out datumOd))
**{
// vypsat chybu, když to není datum

}**
else
// poslat do DB

a pak vkládej do databáze již typ DateTime. To by mělo být v pořádku.

 
Nahoru Odpovědět 6.11.2014 14:22
Avatar
Maros2470
Člen
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Maros2470:

Přetypované jsem to měl, ale zaměňuje mi to den za měsíc a naopak. Chyba bude asi ve formátu, ve kterém se to ukládá do databáze, nebo načítá zpět do text boxu.. Je to pro mně dost velký problém, protože načtené datum používám k výpočtům

 
Nahoru Odpovědět 6.11.2014 15:41
Avatar
Odpovídá na Maros2470
Nikola Sterziková (PaNika):

A do databáze se ti to uloží správně? (Předpokládám, že ano)
Pro načtení z db používám ne moc hezkou konverzi:

tbDatumOd.Text = Convert.ToDateTime(dr["DatumOd"].ToString()).ToShortDateString();

Pokud to načítáš třeba do GridView, lze specifikovat formát, ve kterém se má datum zobrazit.

<asp:BoundField DataField="Datum" HeaderText="xxxx"  DataFormatString="{0:d.M.yyyy HH:mm}" />

Podobně lze specifikovat formát při přetypování z DateTime na String.

datumDo.ToString("d.M.yyyy HH:mm")
 
Nahoru Odpovědět 6.11.2014 16:28
Avatar
Maros2470
Člen
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Maros2470:

Do databáze to ukládá špatně. Do text boxu to z databáze načte tak jak je to uloženo v databázi.

 
Nahoru Odpovědět 6.11.2014 16:46
Avatar
Nikola Sterziková (PaNika):

Pak budeš muset při přetypování ze stringu na datum zadat i CultureInfo.

string datum = "1.5.2014";
DateTime skutecneDatum;
System.Globalization.CultureInfo ci = new  System.Globalization.CultureInfo("cs-CZ");
skutecneDatum = DateTime.Parse(datum, ci);
 
Nahoru Odpovědět 6.11.2014 16:55
Avatar
Maros2470
Člen
Avatar
Odpovídá na Nikola Sterziková (PaNika)
Maros2470:

Pořád stejné. Mám to napsáno takto:

private void btnInsert_Click(object sender, EventArgs e)
         {
             System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("cs-CZ");
             datumRevize = DateTime.Parse(txbDatum1.Text, ci);

             System.Globalization.CultureInfo ci1 = new System.Globalization.CultureInfo("cs-CZ");
             naslednaRevize = DateTime.Parse(txbDatum2.Text, ci1);

             try
             {
                 SqlCommand cmd1 = new SqlCommand(@"Insert Into Revize(Provozovatel, Objekt, Adresa, Odkaz, DatumRevize, NaslednaRevize, Status, CisloRevize, Ic, Predmet, Lhuta)
                                                   VALUES ( '" + txbProvozovatel.Text + "', '" + cmbObjekt.Text + "', '" + txbAdresa.Text + "', '" + odkaz + "', '" + datumRevize + "', '" + naslednaRevize + "', '" + txbStatus.Text + "', '" + txbCislo.Text + "', '" + txbIc.Text + "', '" + txbPredmet.Text + "', '" + cmbLhuta.Text + "' ) ", con);
                 con.Open();
                 cmd1.ExecuteNonQuery();
             }

             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
             }

             finally
             {

                 con.Close();
             }
             trvSeznam.Nodes.Clear();
             try
             {
                 SqlCommand cmd1 = new SqlCommand("SELECT * FROM Revize ", con);
                 con.Open();
                 SqlDataReader dr1 = cmd1.ExecuteReader();
                 while (dr1.Read())
                 {
                     var adresa = trvSeznam.Nodes.OfType<TreeNode>().FirstOrDefault(o => o.Text == dr1["Adresa"].ToString())
                    ?? trvSeznam.Nodes.Add(dr1["Adresa"].ToString());
                     var subcat = adresa.Nodes.OfType<TreeNode>().FirstOrDefault(o => o.Text == dr1["Predmet"].ToString())
                         ?? adresa.Nodes.Add(dr1["Predmet"].ToString());
                     subcat.Nodes.Add(dr1["CisloRevize"].ToString());
                     progressBar.Visible = true;
                     timer1.Enabled = true;
                 }
             }

             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
             }

             finally
             {

                 con.Close();
             }
 
Nahoru Odpovědět 6.11.2014 17:55
Avatar
Odpovídá na Maros2470
Michal Štěpánek:

Když pominu hrozbu SQL injekce ve tvém SQL příkazu, měl bys k zadávání datumu používat komponenty k tomu určené, tzn. DateTimePicker, nebo MonthCalendar, Tam se totiž datum automaticky nastaví tak, jak má být a do DB se uloží ve správném formátu. S TextBoxem a datumem jsou jen problémy.
v SQL příkazech používej parametry, abys předešel problémům "mezi klávesnicí a židlí"...

Editováno 6.11.2014 18:44
Nahoru Odpovědět  +1 6.11.2014 18:42
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Maros2470
Michal Haňáček:

Přesně jak říká Michal Štěpánek, můsíš počítat s tím že tvou aplikaci nebudeš obsluhovat jen ty. Vezmi si jak je např. jednoduché namísto

25.1.2014

napsat

25,1.2014

ty máš problém a uživatel si takového překlepu ani nemusí všimnout. Tak že před tebou jsou dvě cesty, první-strastiplná kdy musíš myslet na všechny tyhle možnosti a převod z textu na datum ošetřovat kódem, kupou kódu. A nebo se vydáš druhou, jednoduší cestou a použiješ komponentu určenou pro to co děláš a ušetříš si tak mraky práce :).

Nahoru Odpovědět  +1 6.11.2014 19:26
Každé rozhodnutí a každý krok v životě nás někam posune. Bohužel jen některé nás posouvají dopředu.
Avatar
Odpovídá na Maros2470
Nikola Sterziková (PaNika):

Souhlasím s Michalem. Určitě při použití sql parametrizuj, Culture Info stačí nadefinovat jednou.
(já raději na většinu věcí používám stored procedure v db, ale je to věcí vkusu a s novými technologiemi jako EF to ztrácí význam)
takže volání je pak něco jako:

System.Globalization.CultureInfo ci = new  System.Globalization.CultureInfo("cs-CZ");
try
        {
                using (MujdatabazovyPomocnik dh = new MujdatabazovyPomocnik)
                {
                        SqlParameter sqlDatumOd = new SqlParameter("@DatumOd", SqlDbType.Date);
                        sqlDatumOd.Value = DateTime.Parse(tbDatumOd.Text, ci);
                        // Nějaký další kód
                        dh.CallStoredProcedureNonQuery("NazevProceduryvDB", sqlDatumOd)
                }

nebo ten param lze zapsat i zkráceněji:

SqlCommand command = new SqlCommand();
command.Parameters.Add("@Datum", vyrobeneDatum);

Validovat bys měl každý vstup od uživatele...

No a ještě dotaz. Sloupec v databázi máš typu DateTime?

Zkus si ten kód krokovat a dívat se, co se ti dá do proměnných při té konverzi na datum v c#. Domnívám se, že jakmile se z textu v C# vyrobí správně datum, tak se už musí i správně uložit do db...

 
Nahoru Odpovědět 7.11.2014 9:45
Avatar
Maros2470
Člen
Avatar
Odpovídá na Michal Štěpánek
Maros2470:

Injekce samozřejmě upravím, mám to jenom jako testovací verzi. Co se týče DateTimePikcer i z této komponenty mi to ukládá do databáze špatně. Prohodí den s měsícem.

 
Nahoru Odpovědět 9.11.2014 10:30
Avatar
Maros2470
Člen
Avatar
Odpovídá na Maros2470
Maros2470:

Jakmile jsem ošetřil injekci, databáze ukládá vše v pořádku.

 
Nahoru Odpovědět 9.11.2014 12:03
Avatar
Odpovídá na Maros2470
Nikola Sterziková (PaNika):

no jasně. :-) tak prima
Když dotaz skládáš VALUES ( '" + textbox.Text .. tak se to do databáze posílá jako text i když před tím převedeš hodnotu na datum. Musí se to pak zase převést zpátky na text a to se převede v nějakým výchozím formátu. Kdežto, když posíláš hodnoty pomocí parametrů, tak když do paramteru dáš hodnotu typu datetime, tak se parametr vytvoří taky typu datetime a do db se uloží správně ve formátu datetime...

 
Nahoru Odpovědět  +1 9.11.2014 12:29
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 14 zpráv z 14.