The best way I can explain the problem is by using 2 database. The first database holds all the real time data. The second database holds data that we update periodically. I need to determine if a value needs to be updated in the second database. Lets say a field called Occupation. To give few scenarios:
DB1 has value of null, DB 2 has value of null, no update.
DB1 has empty value, DB2 has empty value, no update.
DB1 has empty value, DB2 has null value, no update.
DB1 has null value, DB2 has empty value, no update.
DB1 has a value, DB2 has empty, null or any other value, update.
DB1 has a null, empty, whitespace, DB2 has an actual value, update.
To achieve I wrote a method like this:
if (string.IsNullOrWhiteSpace(db1.Occupation)) db1.Occupation = string.Empty;
if (string.IsNullOrWhiteSpace(db2.Occupation)) db2.Occupation = string.Empty;
if (!db1.Occupation.Equals(db2.Occupation)) return false;
return true;
My question is would there be a built in way to achieve the scenarios I have above? I've looking into if (String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase) and object.Equals(str1, str2) But I don't think those handle the scenarios above due to white space and empty string are 2 different values the way I see it. Maybe I am wrong and this is what this post is to find out if there is a better way.
Would this suit your needs?
return ((db1.Occupation?.Trim() + "") == (db2.Occupation?.Trim() + ""));
? protects for null reference exception
.Trim() cleans up white
space
+ "" converts any null to empty
Related
I'm working in Asp.net WCF. I'm displaying a table in front end, with the data taken from back end. One of the column having datatype date, contains Null value in backend. When i try to run the solution it displays error page because of the Null value, for the column. How can i avoid this error ?
I think you're looking for SqlDataReader.IsDBNull Method
Check whether the database field contains null value
Handle it with String.Empty
Here is an sample that I have used
logSource = (!reader.IsDBNull(0)) ? reader.GetString(0).Trim() : "";
From your comments,
ObjUnutilizedOwnershipEntities.Dt_VisaValidFrom = (!IsDBNull(osqlDataReader["Dt_VisaValidFrom"]))
? Convert.ToDatetime(osqlDataReader["Dt_VisaValidFrom"].ToString())
: "";
In an area of my site, I need to control access to a specific set of users.
This is done by checking the user's ID against a table on a SQL server database. If the ID exists then they are granted access:
SELECT 1 FROM admin WHERE userID = #userID
I notice that there are a couple of ways in which I can check for the presence of a row within the database and was wondering if there was any benefit of using either one, or if there was a standard.
The first is by checking for the existence of rows in the SqlDataReader:
if (!SqlCommand.ExecuteReader().HasRows)
{
//redirect
}
The second is to check if the returned value is DBNull using ExecuteScalar():
if (SqlCommand.ExecuteScalar() is DBNull)
{
//redirect
}
Which should I use? Is there a better way? Does it really matter?
The second option because you have less overhead.
However please note
ExecuteScalar returns an object that is
The first column of the first row in the result set, or a null
reference (Nothing in Visual Basic) if the result set is empty
Your query may not return anything, so it is better to check for null instead of DBNull
if (SqlCommand.ExecuteScalar() == null)
{
//redirect
}
Both are same in terms of the performance.
ExecuteScalar only returns the first value from the first row of the dataset. Internal it is treated just like ExecuteReader(), a DataReader is opened, the value is picked and the DataReader gets destroyed afterwards.I also always wondered about that behavior, but it has one advantage: It takes place within the Framework...and you can't compete with the Framework in manners of speed.
Following are the difference between those two:
ExecuteReader():
1.will work with Action and Non-Action Queries (Select)
2.Returns the collection of rows selected by the Query.
3.Return type is DataReader.
4.Return value is compulsory and should be assigned to an another object DataReader.
ExecuteScalar():
1.will work with Non-Action Queries that contain aggregate functions.
2.Return the first row and first column value of the query result.
3.Return type is object.
4.Return value is compulsory and should be assigned to a variable of required type.
taken from
http://nareshkamuni.blogspot.in/2012/05/what-is-difference-between.html
in your case it will not affect much performance so either of them you can use .
ExecuteScalar is typically used when your query returns a single value. If it returns more, then the result is the first column of the first row. An example might be SELECT ##IDENTITY AS 'Identity'.
ExecuteReader is used for any result set with multiple rows/columns (e.g., SELECT col1, col2 from sometable).
SOURCE
When I am making a query for a data from a MS SQL Server database via C# [.Net 4] Code and adding a parameter to the query with a value of "\0", the datareader is obtained without any exception and when i read the data from the datareader, i get the exception.
For testing purposes i have used the "\0" in place of a GUID, is there a way to fix this issue other than at the input end.
I think you are confusing several flavours of Null (.NET Clr null references, Database NULL values and ASCII 0 character literals).
If you want to pass an empty string in C# pass
string emptyString = String.Empty
To pass a null value pass null;
string nullString = null;
However, to pass database NULL, pass DBNull
dbParam.Value = string.IsNullOrEmpty(str)? DBNull.Value : str;
See also SqlParameter with Nullable value give error while ExecuteNonQuery?
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.
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);