Hur ska jag hantera null värde på bästa sätt Problemet är att en Int inte kan vara en null. Vad du får göra är att kolla om dess data är null och då sätta en default -1 eller annars dess värde. Fast <b>Convert.ToInt32</b> har inbyggd nullhanterare?! Vad man då kan göra är att bygga in konrtoll för DBNull oxå i en egen Class... Jag tror det är DBNull som måste hanteras som någon påpekade. Du kan göra så här men det rekomenderas att du även gör något åt vad som händer när det är null. Sätt dem till -1 eller liknande. Eller om man skall ta till sig Johan Normens senaste krönika ;) : Hejsan.. Jag skrev lite om Nullobject i min blog för er som är intresserade: Hej ok. Ahh ok.. För att hantera null-värde på bästa sätt bör du helt enkelt designa ditt databas-schema så att nullvärden inte behövs. "Låt säga att du har int i dbn som du inte vill a defaultvärden på för att du vill hantera dess null som olika default värden i din applikation" "Detta var bara ett grovt exempel vanligtvis har man ju netto, brutto antal m.m. Vad jag vill peka på är att det inte alltid går att köra med en pilicy där null aldrig får förekomma. Allt beror på systemets krav. Om "någon" har designat DBn så från början är vi väl överens om att man får bita i det sura äpplet. Jag blir bara intresserad av att se ett exempel där man inte KAN klara sig utan null. Det finns inget sådant exempel. Man kan alltid klara sig utan null. Hej, varför inte använda Try...Catch "För att hantera null-värde på bästa sätt bör du helt enkelt designa ditt databas-schema så att nullvärden inte behövs." Det är inte farligt att använda null. Det hela handlar bara om hur man som designer vill nyttja sin data. Jag vill bara flika in hör lite (Intresant diskution).hantera null värde
jag har det så här och det kan vara så att antingen bookID eller movieID = null.
jag ska sen skicka in dessa i en metod och om de är null så ska jag skicka in null i den
Just nu så kraschar den för att bookid är null.
Hur ska jag skriva?
<code>
while(MyReader.Read())
{
ID = Convert.ToInt32(MyReader["ID"]);
BookID = Convert.ToInt32(MyReader["BookID "]);
MovieID= Convert.ToInt32(MyReader["MovieID"]);
}
MyReader.Close();
</code>Sv: hantera null värde
int BookID = -1;
if(MyReader["BookID"] != null)
BookID = Int32.Parse(MyReader["BookID"].....
else
för att underlätta det hade jag byggt en egen IntUtil klass eller nått. Eller en Nullable klass med en metod IsNull...
public class Nullable()
{
public static bool IsNull(object value)
{
return(value == null);
}
}
if(!Nullable.IsNull(MyReader["BookID"])
BookID = Int32.Parse(MyReader["BookID"].....
Mvh JohanSv: hantera null värde
Från reflector:
public static int ToInt32(object value)
{
if (value != null)
{
return ((IConvertible) value).ToInt32(null);
}
return 0;
}
Det måste vara så att den inte löser <b>DbNull</b> eller?
Sv: hantera null värde
Typ:
public class Nullable()
{
public static bool IsNull(object value)
{
return(value == null || value == DBNull);
}
}
Eller om man bygger sig en egen liten convert metod där man tar med DBNull i kontrollen.
Mvh JohanSv: hantera null värde
while(MyReader.Read())
{
ID = Convert.ToInt32(MyReader["ID"]);
if (MyReader["BookID"] != DBNull.Value)
BookID = Convert.ToInt32(MyReader["BookID "]);
if (MyReader["MovieID"] != DBNull.Value)
MovieID= Convert.ToInt32(MyReader["MovieID"]);
}
MyReader.Close();Sv: hantera null värde
while(MyReader.Read())
{
ID = GetInt32(MyReader["ID"]);
BookID = GetInt32(MyReader["BookID "]);
MovieID= GetInt32(MyReader["MovieID"]);
}
MyReader.Close();
public int GetInt32(object obj)
{
if ( obj != null && obj != DBNull.Value )
{
return Convert.ToInt32(obj); // Convert if not null
}
else
{
return -1; // Default value
}
}
Sv: hantera null värde
Man kan baka in det i en egen reader om man vill också, så att man får
public int GetInt32(int i)
{
if(_dataReader.IsDBNull(i))
return Default_Int32; // -1
else
return _dataReader.GetInt32(i);
}
Eller eftersom det gäller en referens till ett annat objekt så skulle man kunna skapa en keyklass som har ett defaultvärde som är nullobjekt av keyklassen ungefär som johan beskriver med nullobjekt, http://www.refactoring.com/catalog/introduceNullObject.html
Sv: hantera null värde
http://www.nsquared2.net/johan/viewpost.aspx?PostID=4
Kom gärna med synpunkter.
Men det är nog riktigt lämpligt i ett såndat case som frågan gäller.
Att kapsla in readenr och göra den global är nog ingen bra idé. Spårbarheten minskar då. Sedan kan du få roliga fel i fall du kör close på readern för att du 'kanske' inte vet hur metoden ser ut. Det låter som caset inte är unikt för just den kontroll han skall göra, så jag hade lagt min egna convert i en egen klass
för att sedan kunna återanvända den på flera ställen.
Se min krönika:
http://www.pellesoft.se/documents/pageblank.aspx?id=12006
Kom även där med synpunkter, frågor eller idéer och tankar.
Mvh JohanSv: hantera null värde
Kan du utveckla lite vad du menar med:
"Att kapsla in readenr och göra den global är nog ingen bra idé. Spårbarheten minskar då. Sedan kan du få roliga fel i fall du kör close på readern för att du 'kanske' inte vet hur metoden ser ut."
Är inte riktigt med på vad du menar.Sv: hantera null värde
Vad jag menar är detta:
public int GetInt32(int i)
{...}
{
if(_dataReader.IsDBNull(i))
return Default_Int32; // -1
else
return _dataReader.GetInt32(i);
}
du har här din reader i metoden GetInt32.
Tänk dig detta senarie.
SqlDataReader this_dataReader = command.ExecuteReader......;
int value = GetInt32(3);
int value2 = GetInt32(4);
this_dataReader.Close();
kod....
int value 3 = GetInt32(6); <--- Exception... Din reader är stängd.
Säg att du inte ser implementationen i denna metod, då har du ingen aning om att den ens använder en reader.
Plus en massa andra faktorer som skulle bli en uppsats om jag berättade varför jag inte tycker du skall göra på det sättet. Men här har du en liten hint...
mvh JohanSv: hantera null värde
Sorry, slarvigt av mig innan.. det jag menade var att du implementerar Idatareader i din egna datareader så att det blir
IDataReader reader = new NullSafeReader(command.ExecuteReader());
int value = reader.GetInt32(1);
Sv: hantera null värde
Sv: hantera null värde
"För att hantera null-värde på bästa sätt bör du helt enkelt designa ditt databas-schema så att nullvärden inte behövs."
Det där är en designfråga. Låt säga att du har int i dbn som du inte vill a defaultvärden på för att du vill hantera dess null som olika default värden i din applikation. Säg att du skulle sätta 0 som default, detta är ett helt vanligt kodkänt värde för antal produkter. Att sätta -1 skulle kunna betyda rest på en produkt. null skulle däremot betyda att något helt annat. Varken rest eller antal. Detta var bara ett grovt exempel vanligtvis har man ju netto, brutto antal m.m. Vad jag vill peka på är att det inte alltid går att köra med en pilicy där null aldrig får förekomma. Allt beror på systemets krav.
Mvh JohanSv: hantera null värde
Varför designa sina tabeller på ett sånt sätt att man måste ha default värden som ex betyder rest på en produkt? Då anser jag att designen är felaktig. Då borde man ha en tabell över produkter och en annan med antal på olika produkter som refererar till produkttabellen.
EDIT: Sen är det naturligtvis en anna sak om man inte själv har designat DBn...Sv: hantera null värde
"
Jag sa att det inte är vanligt ;-) Jag tog bara ett exempell ur luften för att förklara ett case. Trodde jag var tydligt med att förklara att detta exempel inte var det bästa... :-)
Och som du sa, någon kan ju ha byggt på det viset :-) Huga säger jag bara då...
Mvh JohanSv: hantera null värde
Sv: hantera null värde
Ibland blir dock designen så pass mycket enklare ifall man kan utnyttja null, att det är värt att göra det.Sv: hantera null värde
Ja du... Av samma anledning att data i en Dictionary kan vara null kan det ju vara det i en databas oxå.
Jag kan inte direkt komma på ett användarfall nu. Men det finns fall då man inte vill ha något värde då det genererar olika betydelser för applikationerna. Jag själv kör inte med null i de saker jag gjort hittils. Men jag vet fall där jag diskuterat detta med andra. Då de varken kunde ha emtpy string eller siffra.
Kommer dock inte ihåg vilket case det var... :-( så jag kan inte dra upp ett exempel där.
Skall se om detta kan hålla..
Tänk dig att du har en skala -250 000 - 250 000 alla siffror är godtagbara. Nu vill du hitta poster där
siffran inte satts för att en viss beräkning inte hunnit genomföras på x antal inlagda uppdrag. Där siffran 0 oxå är beivs på registering. Då vill man ju leta på dess null. Att ex sätta allt till 0 och skapa en flagga som betyder beräknad är ju förvisso oxå en lösning. Frågan är om flagga är aktuellt i ett kritiskt system där det skall genomföras över flera 100 000 beräkningar i secunden?
Bara tänker runt lite nu... Min filosofi i denna värld är att ALDRIG säga att inget är möjligt eller inte kommer att behöva nyttjas. Det anser jag vara en dåligutvecklare.
Mvh JohanSv: hantera null värde
try
{
BookID = Convert.ToInt32(MyReader["BookID "]);
}
catch
{
//BookID = Default value;
}Sv: hantera null värde
Detta tycker jag känns mycket konstigt. Null finns och varför inte använda det? Säg att man lägger in en händelse, och att man sedan skall ange när denna händelse har inträffat. Men när man lägger in den så vet inte när den kommer att ske, minst ett fält kommer att bli null.
Visst man kan arbeta sig runt så att man inte behöver använda null, men varför? null anger att det inte finns något inmatat i det fältet och att det är okej. Sv: hantera null värde
Allt är politik och dialekter. Gör som du tycker är bäst.
Mvh JohanSv: hantera null värde
Ett exempel där NULL i databas är användbart är då ett värde inte är fastställt. Tex om en varchar är NULL eller Int så har den kolumen inget värde. Men om en varchar sätts till "" (tom sträng) och int till 0 så har den ett värde. Det finns situationer där man vill kunna få reda på om ett fält har ett värde eller inte, tex om Int är 0 så har den ett värde. I C# 2.0 kommer Nullable<T> att finnas för att kunna få value types att kunna vara null bara. Idag är en Int alltid ett värde, du kan inte se om du har icke tilldelat ett värde (Jo om du bestämmer dig för ett värde som ska motsvara ett NULL värde, tex 0 eller -1).
Vet inte om ni blev så mkt kolkare på detta eller om ni förstår vad jag syftar på. Men jag hoppas det ;)
/Fredrik Normén NSQUARED2
http://normen.mine.nu/myblog