Dataset allowing Null values even when AllowDBNull = False? - c#

I have designed a dataset using VS2008 dataset designer. In one of the datatables, I have set "AllowDBNull" property of most of the columns to be False. However, still if I create a DataRow containing null values for these columns, this datatable accepts this row, without any error.
Am I not understanding something here? Please advice. Thank you.
Edit Mike Spross' excellent explanation however, brings forth another question. How do we check text fields if they are System.DBNull? It is surprising that DataSets are not considering a string "" as System.DBNull and throwing an exception. Or is it not?
Edit I think I have found the problem and reason. I am initializing a new row of the DataTable, before filling in the values to that row. While initializing the row, default value for string, ie, "" might be being filled in that column. I think that's it? Any ideas about this?

The short answer is:
System.DBNull.Value != null
The longer answer is:
In C#, the concept of a NULL value in SQL is represented by the Value property of the System.DBNull class. When dealing with a database, the more familiar C# null doesn't actually mean "null value."
When you set a database column to null, ADO.NET will initialize the column to whatever the default value is for that column (for example, an int column would be initialized to 0). That is, using null can actually cause a non-null value to end up in the database, and therefore you won't get an error.
If you instead set a database column to System.DBNull.Value, the column will actually be set to NULL. This is the situation that AllowDBNulls == false will prevent you from doing.

Regarding your "bonus" ;-) question: NULL (no string) and "" (empty string) are two different things. So it's perfectly reasonable to treat them differently. It's the distinction between null and DBNull that is messing things up. If nullable types had been available at the time of designing ADO.NET, things probably would be a lot easier. But before .NET 2.0, there was no way to represent e.g. a "null integer".

Are you exactly assigning NULL values or an empty string to those columns? If you don't assign any value to a column, it will default to NULL (if a DEFAULT constraint is not imposed). Else you can assign a NULL value by doing -
ds.Tables[0].Rows[0]["Col"] = null;
If you are assigning an Empty string to those columns, it's not equal to NULL.
And if you have a NULL value in a column which has been marked as NOT NULLABLE, it will throw an error -
Column 'Col1' does not allow nulls.
EDIT:
By NOT NULLABLE, I mean AllowDBNull = false.
Your code seems correct. Can you try trimming the text?
Here's the whole code -
DataTable dt = new DataTable();
DataColumn column = new DataColumn("Col1");
column.AllowDBNull = false;
dt.Columns.Add(column);
DataRow dr = dt.NewRow();
dr["Col1"] = null;
dt.Rows.Add(dr);

Related

DataGridView cell treats empty editable cell as a null, ignores DataGridViewCellStyle.NullValue property

I have a DataGridView with 3 columns, two of which are user-editable.
I was getting a NullRef exception when accessing the cell's value as such
someObject.Property = dgv.Rows(x).Cells(y).Value.ToString()
Which was obviously because I'm not checking for null before using the value. So instead of just checking for a Nothing value (which I will do now, never fear) I decided to change the object that initializes the DataGridView to never contain null for the string property that populates the cell. I just used String.Empty instead.
I thought everything would be well and good, but it seems that when I edit the cell and leave it blank it treats it as a null value instead of String.Empty. I've handled the the CellBeginEdit, CellEndEdit and CellLeave events trying to find where it's getting this magical null value from to no avail.
I saw the DataGridViewCellStyle.NullValue property on the MSDN, which I thought would be the answer but, as it turns out, the NullValue property defaults to String.Empty so that doesn't make a lot of sense.
Obviously the simple answer here is "just check for null before you use it", but why can't I force it to treat an empty string as an empty string instead of a null?
datagrid cell values are objects, an empty string is null.
You could convert it to a string and then check for string.empty but it's not far off just checking if it's nothing.
dim _value as string = dgv.Rows(x).Cells(y).Value
someObject.Property = _value
or write a function to check
Public Function checkForNull(_value as object) as string
If _value is nothing then return string.empty else return _value.tostring()
End Function
....
SomeObject.Property = checkForNull(dgv.Rows(x).Cells(y).Value)

How do I get a value from a database using Oledb, I keep getting a DBNull exception?

int weaponDamage = Convert.ToInt32(dt.Rows[randomItem][2]);
// dt= DataTable
// randomItem = randomly chooses a row from the datatable
That code throws
"InvalidCastException was unhandled, Object cannot be cast from DBNull to other types".
Yes I am using the correct column and yes the entire column has values. The odd thing is sometimes the program ran, but then next time it gives the exception again. Could the problem lie with my Data Type in the database? It is set to Number and the Field Size property to Integer
Try some mitigation:
int weaponDamage = 0;
if (dt.Rows[randomItem][2] != DBNull.Value){ // I think, I'm doing this from memory.
if (int.TryParse(dt.Rows[randomItem][2].ToString(), out weaponDamage){
// Do whatever you need.
}
}
Check that the column has a value other then NULL. Then do a safe-cast of that value into an int.
There's no reason why you should randomly be getting a value one time, and then a NULL the next to be honest. That would imply that the data in the table is changing, or you are looking at different rows of data? Not sure, but I'd add some defensive coding in there to help.
What if you print the returned value first to see if it is a numeric, a string, a random object. You should also use proper try/catch blocks to avoid unhandled exceptions.

Autogenerate columns null values

I want to save null values to a decimal column(allows nulls on db) on a wpf datagrid (with autogenerate columns).
It doesn't allow me to save nulls and shows red error box.
I suspect you are running into a problem that I had but it was a simple text box (not a datagrid). You think you are passing a null but you are really passing string.empty which is neither null nor a decimal. I fixed it with a converter to convert string.empty to null. H.B. (the same H.B.) that edited your question answered mine.
Cannot Assign a Null Value to a Nullable Int32? via Binding
to which kind of database are you binding your datagrid to ? for instance if you bind it to a datatable with ado.net, the datatable is not aware of the underlying sql schema unless you update it yourself. --> see http://support.microsoft.com/kb/310128
with linq2sql it should work fine without this update, with others like MySql i don't know.
Just add this code in AutogeneratingColumn event:
if (e.Column.ToString() ==
"System.Windows.Controls.DataGridTextColumn")
{
(((System.Windows.Controls.DataGridBoundColumn)(e.Column)).Binding).TargetNullValue
= string.Empty;
}

Int inadverantly cast to string behind my back

This was originally a problem with Crystal Reports but I tracked down the issue to a single line of code:
foreach (DataRow dr in ds.Tables["CurrentScheduleFields"].Rows)
if (dr["MY_FIELD"].ToString() == string.Empty)
dr["MY_FIELD"] = 0;
I am using an Oracle database. The field is actually a Numeric(2). We are using straight ADO.NET and no Nullable types in this case. In one case, the field in question has a value of an int and the above line of code is fine. The other case, the value of the field is DBNull.Value, and the above or something is converting the 0 to "0" ( a string).
dr is not a `DataReader foreach (DataRow dr in ds.Tables["CurrentScheduleFields"].Rows)
Does anyone know why?
My browser is not letting me click on the Add Comments, so I am adding stuff here. Why can't I do if (dr["MY_FIELD"] == DBNull.Value)
dr["MY_FIELD"] = 0;
the debugger hits that and converts to a string with a value of "0", not 0. I guess the first answer handles this, "So the problem may be that the first "MY_FIELD" is null, convincing ADO.NET that the type for that column is a string." So it's now string with DBNull.Value in it?
My browser is locked down. I can't click on anything except edit this but:
ANSWER: Handle this on the Crystal side by changing the formula to handle a string for this value and not an int. It works!
In some cases, when dealing with DataTable, I've seen it try to "guess" at the type of a column based on the value in that column in the first row in your set. So the problem may be that the first "MY_FIELD" is null, convincing ADO.NET that the type for that column is a string.
You may want to set the schema for your DataTable before you try to load it.

DBNull warnings when performing stored procedure

One column in my database (of type double) has some null values.
I am executing a sored procedure to get the data in my app
wipDBTableAdapters.XLSFacturiTableAdapter TAFacturi = new wipDBTableAdapters.XLSFacturiTableAdapter();
var dtfacturi = TAFacturi.GetData(CodProiect);
Then i try to do something like this:
if (dtfacturi[i].CANTITATE == null)
{
//do something
}
this is giving a warning :
The result of the expression is always 'false' since a value of type 'double' is never equal to 'null' of type 'double?
However when i run my code i get the following exception:
StrongTypingException
The value for column 'CANTITATE' in table 'XLSFacturi' is DBNull.
How am I supposed to resolve this ?
While working with data in DB and need to check NULL values use DBNull class instead of .NET null.
Database NULLs are different from null, you should use IsDBNull to check for database NULLs.
Edit: Mixed up VB.Net with C#
Compare with DBNull.Value rather than the VB specific IsDBNull.
Try this:
if (dtfacturi[i].CANTITATE == DBNull.Value)
{
//do something
}
A value of type 'double' is indeed never null; if you want to export into an array of doubles, you need to have two columns in the database, one containing the data and one containing a flag as to whether the data is valid or not.
This is really a bug in your database-to-array adapter code; I can't find any google hits for XLSFacturiTableAdapter so I'm not sure who to shout at.
DBNull is not null
Check DBNull documentation on MSDN
Try this test :
if (DBNull.Value.Equals(dtfacturi[i].CANTITATE))
{
//do something
}
When using TypedDataSets, check if coloumn is null this way..
if (dtfacturi[i].IsCANTITATENull())
{
//do something
}
Also note that, C# null is different than Database null. Type of your coloumn is double which is a value type that can never be null. In order to check if your coloumn value is null you need to compare it with DBNull.Value.

Categories

Resources