|
[ krvopije @ 11.11.2004. 21:36 ] @
| Dakle,
radim jednu ASP.NET aplikaciju koja se naravno naslanje na baszu (MSSQL 2000) i nekom trenutku zelim da iz baze izvucem neke podatke da bih u biznis sloju napravio jedan objekat. Taj objekat ima propertiy koji je tipa int, i cija se vrednost popunjava odgovarajucom iz baze. Problem nastaje kada je ta vrednost u bazi NULL a C# ne dozvoljava postavljenje int na NULL. Kako ze zaobilazi ovakva situacija? tj. sta da svtavim za vrednost tog int-a????
Pozdrav |
[ krvopije @ 11.11.2004. 23:14 ] @
Da sam sebi odgovorim:
int var=Convert.ToInt32(null)
to mi je trebalo
[ erkan @ 16.11.2004. 11:19 ] @
moze i prilikom SELECT upita koliko je meni poznato (ako mislimo na istu stvar):
SELECT isnull(ime_kolone, 0)
[ krvopije @ 16.11.2004. 11:31 ] @
Pazi, nije ista stvar, je ne zelim da setujem promenjivu na 0 kada je u bazi NULL, jer to nije isto. 0 je poznato a NULL je nepoznato. Tako da zelim da prenesem to NULL iz baze na preomenjlvu. Jer sta ako vrijednost u bazi moze biti i NULL a isto tako i 0, pa kada vracam rezultat iz baze u oba slucaja dobijam 0, sto ne zelim!
[ mmix @ 16.11.2004. 14:37 ] @
Tacno, nije isto, sto nas vraca na tvoj odgovor, posle komande:
int var=Convert.ToInt32(null)
var ce biti 0, ne null  . Sta vise, kad vrsis upit nad poljem u DataRow, ako je polje u bazi NULL, vrednost polja nece biti null, nego DBNull.Value, a ako pokusas da izvrsis
int var=Convert.ToInt32(DBNull.Value)
dobices:
Object cannot be cast from DBNull to other types.
bas da bi se sprecilo da se NULL iz baze u kodu tretira kao 0.
Jedna od zaobilaznica je da promenljivu var deklarises kao object i da "boxujes" integer u nju i da imas neku konstrukciju nalik ovoj:
object var;
if (dr["Polje"] is DBNull)
var = null;
else
var = Convert.ToInt32(dr["Polje"]);
ali onda ne mozes da se zatrcis pa da koristis var kao integer bez da proveravas da li je null
[ krvopije @ 16.11.2004. 14:55 ] @
Citat:
object var;
if (dr["Polje"] is DBNull)
var = null;
else
var = Convert.ToInt32(dr["Polje"]);
E, bas to je ono sto mi treba! Naravno da cu da provjeravam da li je NULL prije upotrebe!
Kada smo vec tu, deklarisanje promjenjive tipom object pa posle pretvaranje u u int, da li ima nekih mana?
Hvala
[ Dragi Tata @ 16.11.2004. 14:57 ] @
Zato valjda u .NET 2.0 uvode nullable types.
[ krvopije @ 16.11.2004. 15:08 ] @
Jeste. ali dok to vrijeme ne dodje onda ovako!
[Ovu poruku je menjao krvopije dana 16.11.2004. u 19:11 GMT+1]
[ mmix @ 16.11.2004. 17:25 ] @
Citat: Dragi Tata: Zato valjda u .NET 2.0 uvode nullable types.
Bas me interesuje nasta ce to da lici u praksi. I sta ce biti zrtvovano zarad ove fleksibilnosti.
ako i najobicniji for-each nad nizom integera mora za svaki element da proverava da li je null, ode mas' u propas  . A sta cemo tek sa deljenjem? Novi exception (EDivideByNull  )?
[ Dragi Tata @ 16.11.2004. 17:32 ] @
Ne verujem da će to biti problem. Koliko sam razumeo, ne omogućava se postojećim tipovima da dobiju vrednost null, već se uvode posebni "paralelni" tipovi koji mogu da budu null. Npr:
Code:
int? x = null; // nullable - obrati paznju na '?' u deklaraciji
int y = 123; // stari, dobri int
[ mmix @ 17.11.2004. 00:08 ] @
Hmm, možda sam ja samo stari paranoic, ali taj int? mi jako liči na boxovani int  samo je sintaksa malo olakšana...
[ ZokiR @ 17.11.2004. 00:17 ] @
Jedan od načina za rad sa NULL vrednostima iz SQL Server baze je korišćenje tipova iz System.Data.SqlTypes namesmace-a (SqlInt32, SqlString, SqlDateTime...)
Dakle ako imaš
SqlInt32 var = dataReader.GetSqlInt32(0);
i ako je vrednost u bazi NULL, var će imati vrednost SqlInt32.Null, a var.IsNull će vratiti true.
Pored podrške za NULL vrednosti, ovi tipovi imaju istu preciznost kao i ekvivalentni tipovi u bazi čime se izbegava gubitak informacija u konverziji, a i performanse su bolje. Evo šta MSDN kaže na tu temu:
Citat: The System.Data.SqlTypes namespace provides classes for native data types within SQL Server. These classes provide a safer, faster alternative to other data types. Using the classes in this namespace helps prevent type conversion errors caused in situations where loss of precision could occur. Because other data types are converted to and from SqlTypes behind the scenes, explicitly creating and using objects within this namespace results in faster code as well.
[ ZokiR @ 17.11.2004. 00:35 ] @
Citat: mmix: Hmm, možda sam ja samo stari paranoic, ali taj int? mi jako liči na boxovani int ;) samo je sintaksa malo olakšana...
int? je u stvari samo C# skraćenica za Nullable<Int32> (dakle, nema novih "paralelnih" tipova koji podržavaju null, nego se isto postiže pomoću nove Nullable klase i generics-a)
[ krvopije @ 17.11.2004. 09:01 ] @
Dakle, sta da radim ja?
Kada kreiram objekat sastavljen od nekoliko varijabli(vrijednosti su iz baze), da onda koristim za sve varijable koristim tipove System.Data.SqlTypes?
Sta ciniti?
[ mmix @ 17.11.2004. 19:35 ] @
Citat: ZokiR: Jedan od načina za rad sa NULL vrednostima iz SQL Server baze je korišćenje tipova iz System.Data.SqlTypes namesmace-a (SqlInt32, SqlString, SqlDateTime...)
Nazalost nijedan od ovih tipova nije serializable, pa im je upotreba prilicno limitirana na prosti read i write iz baze. Ne postoji podrska za ove tipove u Typed DataSet, sto te na kraju primorava da sve radis pesaka. Nije nemoguce, al nije bas ni prijatno, narocito ako se i gridovi pojave kao consumeri.
Citat: ZokiR: int? je u stvari samo C# skraćenica za Nullable<Int32> (dakle, nema novih "paralelnih" tipova koji podržavaju null, nego se isto postiže pomoću nove Nullable klase i generics-a)
Sad ste me zaintrigirali pa se raspitah malo. Oni to jos uvek prelamaju kako ce i sta ce  i koliko vidim ECMA jos nije nista rekla na tu temu. Ali bottom line opet se svodi na boxovanje value tipa unutar objekta, samo sto ce objekat biti malo jace tipiziran nego pre. Cak i provera za null mora da ostane, samo se koristi negativna logika (umesto isnull ide hasvalue), jer ce u suprotnom bez ove provere citanje default propertija Value pljunuti EValueIsNull exception. Koliko vidim jos niko nista ozbiljno ne komentarise na temu Nullable generics <-> ADO.NET, a to je ono sto nas pretezno intrigira.
[ ZokiR @ 18.11.2004. 04:58 ] @
Citat: mmix: Nazalost nijedan od ovih tipova nije serializable, pa im je upotreba prilicno limitirana na prosti read i write iz baze. Ne postoji podrska za ove tipove u Typed DataSet, sto te na kraju primorava da sve radis pesaka. Nije nemoguce, al nije bas ni prijatno, narocito ako se i gridovi pojave kao consumeri.
Da, sve to stoji. Postoji jedan open source projekat koji nudi slične tipove sa mogućnošću serializovanja ( http://nullabletypes.sourceforge.net/) ali ostaje problem DataSetova, bindinga itd.
Citat: mmix: Koliko vidim jos niko nista ozbiljno ne komentarise na temu Nullable generics <-> ADO.NET, a to je ono sto nas pretezno intrigira.
Pretpostavljam da ADO.NET i dalje neće podržavati implicitnu konverziju iz null u DBNull i obratno, tako da će to morati da se radi ručno (mada će u C# to biti malo olakšano novim operatorom ??, npr. cmd.Parameters[0].Value = i ?? DBNull) ali bi bilo fino kada bi binding i automatsko generisanje "strongly typed" DataSetova imali podršku za Nullable<T>.
[ zuxbg @ 18.11.2004. 13:58 ] @
Database NULL "vrednost" i .NET 1.1
1. Način - korišćenje typed dataseta
Ako kreirate typed dataset MyDataset sa tabelom MyTable koja ima nullable kolonu MyColumn
MyDataset ds = new MyDataset();
a) provera:
if( ds.MyTable[0].IsMyColumnNull() ) {...}
b) set na null
ds.MyTable[0].SetMyColumnNull();
Znači, okruženje generiše dve pomenute metode: IsMyColumnNull i SetMyColumnNull.
2. Način - korišćenje parametara
Kada izvršavamo DML komande (SELECT, DELETE, INSERT, UPDATE) nad bazom koristimo prametrizovane stored procedure (mogu i sql queriju, ali svi znamo da tako ne treba!). Polja koja želimo da budu null u bazi predstavimo kao parametre čija je "vrednost" null. Primer koristi Oraclov data provider ODP.NET, na MS-ov.
OracleConnection con = null;
try
{
// Connection
con = new OracleConnection(m_conStr);
con.Open();
// Command
string cmdQuery = "mlp.login_f";
OracleCommand cmd = new OracleCommand(cmdQuery);
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
// Params
//
// ZahtevId
//
OracleParameter opZahtevId = cmd.Parameters.Add("a_zahtev_id", OracleDbType.Char, 5, ParameterDirection.Input);
opZahtevId.Value = zahtevId;
//
// JMBG
//
OracleParameter opJmbg = cmd.Parameters.Add("a_jmbg", OracleDbType.Char, 13, ParameterDirection.Input);
opJmbg.Value = System.Convert.DBNull;
...
cmd.ExecuteNonQuery();
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
finally
{
if (con != null)
{
con.Close();
}
}
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|