ASP.Net C# CreateParameter with empty string - c#

In my ASP.net C# web project I have a query command object that has parameters. I use the following code to fill the parameters:
DbCommand command = conn.CreateCommand();
command.CommandText = query;
DbParameter param = command.CreateParameter();
param.ParameterName = parameter;
param.DbType = DbType.String;
param.Value = value;
This code works for all strings except for empty ones. If I would leave an input field blank, it would pass the value as "". If this happens I receive the following exception:
ORA-01400: cannot insert NULL into (string)
Is there a way that would allow me to insert blank strings into the database?
I use an Oracle database and I'm using System.Data.OracleClient as provider.

If you want to insert an empty string, you have to allow NULL values. Otherwise Oracle silently converts the empty string into NULL and you'll get the exception.
Another option would be to insert an empty string with a space ' ' but i think that would be a pain.
Here are further informations on why Oracle does it this (non standard) way:
Why does Oracle 9i treat an empty string as NULL?

If the value is null, set param.Value = DBNull.Value, rather than setting it to null:
if (value == null)
{
param.Value = DBNull.Value;
}
else
{
param.Value = value;
}

try
param.Value = string.IsNullOrEmpty(value) ? DBNull.Value : value;

Related

Unable to insert null values in nullable column via stored procedure in C#

I have a SQL table where column is set to null. Now I am passing the null value from code via stored procedure and it throws an error which is, Procedure or function 'MyStoredProcedure' expects parameter '#Parameter', which was not supplied.
Now Confusing part for me is, if I add null condition and than pass DBNull.Value, it works fine but if I pass direct parameter which could be null than it throws error. I am trying to understand why? Am I missing something here?
Note: Just for information, passing parameter could be null based on the requirement.
Code:
string connString = _dbContext.Database.Connection.ConnectionString;
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
SqlCommand cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
scheduledEndDateTime = !string.IsNullOrEmpty(bulkUpdateSchedule.EndDate) && !string.IsNullOrEmpty(bulkUpdateSchedule.EndTime)
? (DateTime?)
Convert.ToDateTime(bulkUpdateSchedule.EndDate + " " + bulkUpdateSchedule.EndTime)
: null;
//This Fails
cmd.Parameters.AddWithValue("#scheduledEndDateTime", scheduledEndDateTime);
//This Works
if (scheduledEndDateTime != null)
{
cmd.Parameters.AddWithValue("#scheduledEndDateTime", scheduledEndDateTime);
}
else
{
cmd.Parameters.AddWithValue("#scheduledEndDateTime", DBNull.Value);
}
cmd.ExecuteReader();
connection.Close();
}
Stored Procedure:
ALTER PROCEDURE [dbo].[InsertScheduledBulkUpdateRecords]
#scheduledEndDateTime DATETIME,
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO ScheduledBulkUpdate (ScheduledEndDateTime)
VALUES (#scheduledEndDateTime)
END
Table Structure screen shot:
You've pretty much answered your own question null and DBNull.Value are different things. Where DBNull.Value means something to the database provider than null doesn't.
From MSDN on DBNull:
Do not confuse the notion of null in an object-oriented programming
language with a DBNull object. In an object-oriented programming
language, null means the absence of a reference to an object. DBNull
represents an uninitialized variant or nonexistent database column.

How can I insert a null value into Sql Server date column using asp.net and command parameters

I have the following code:
SqlDateTime sqldatenull = SqlDateTime.Null;
sSql = "INSERT INTO mydb.dbo.myTable(FromPeriod) Values (#FromPeriod)";
if (sFromPeriod.Length == 0) {
cmd.Parameters.Add("#FromPeriod", SqlDbType.DateTime);
cmd.Parameters["#FromPeriod"].Value = sqldatenull;
} else {
cmd.Parameters.AddWithValue("#FromPeriod", sTempFromPeriod);
}
cmd.ExecuteNonQuery();
sFromPeriod is a date and when it's length is zero, I receive error: Conversion failed when converting date and/or time from character string. When sFromPeriod has a value, the code works fine. I have also used DBNull.Value in place of sqldatenull and received the same error. What am I missing?
Consider using DBNull.Value instead of SqlDateTime.Null.
For example:
cmd.Parameters["#FromPeriod"].Value = DBNull.Value;

INSERT query - Null vs Empty String .. does it matter?

I have the following code that inserts some data into an Access table. It starts with a comma delimited line that I split into a string array, then add the array elements as parameters:
string line = "one\ttwo\t\tfour";
string[] values = line.Split('\t');
using (OleDbCommand com = new OleDbCommand("INSERT INTO [MyTable] (" +
"[Field1], [Field2], [Field3], [Field4] "
") VALUES (" +
"?, ?, ?, ?" +
")", con))
{
com.Parameters.Add("#p0", OleDbType.Char, 255).Value = (object)values[0] ?? DBNull.Value;
com.Parameters.Add("#p1", OleDbType.Char, 255).Value = (object)values[1] ?? DBNull.Value;
com.Parameters.Add("#p2", OleDbType.Char, 255).Value = (object)values[2] ?? DBNull.Value;
com.Parameters.Add("#p3", OleDbType.Char, 255).Value = (object)values[3] ?? DBNull.Value;
com.ExecuteNonQuery();
}
In the above example, #p2 will not have a value. It gets inserted into the Access table as a blank value, instead of a null value. At least I think I'm explaining that correctly. If I query for Field3 is Null I get no results. If I query for Field3 = "" I do get results. Does it matter if it's blank or null? Is there a 'preferred' option?
Thanks!
Well, null is definitely not the same as an empty string. So, yes, it matters. But only in your domain. So in other words, if the field isn't really nullable and Access is interpreting DBNull.Value as an empty string, then you just have to keep that in mind when looking for rows with no value. If the column were nullable in Access you wouldn't be seeing this behavior.
However, if the field in nullable, then I would recommend you actually just send in null instead of DBNull.Value. So, in other words:
values[0];
instead of:
(object)values[0] ?? DBNull.Value;
Original statement:
com.Parameters.Add("#p2", OleDbType.Char, 255).Value = (object)values[2] ?? DBNull.Value;
From the description it is sending the empty string '' from values[2], not the DBNull.Value. I would explicitly convert the empty string (or null) rather than using the null-coalescing operator (??):
com.Parameters.Add("#p2", OleDbType.Char, 255).Value = String.IsNullOrEmpty(values[2]) ? DBNull.Value : values[2];
Added: As the type-specification (OleDbType.Char) is preventing this from sending DBNull to the database, I would revert to AddWithValue:
com.Parameters.AddWithValue("#p2", String.IsNullOrEmpty(values[2]) ? DBNull.Value : values[2]);
This doesn't specify the type so should accept DBNull or the string. I prefer this approach anyway: if we specify the type we need to ensure that it is entirely consistent with the field data-type -> let C# work this out.

Exception when AddWithValue parameter is NULL

I have following code for specifying parameters for SQL query. I am getting following exception when I use Code 1; but works fine when I use Code 2. In Code 2 we have a check for null and hence a if..else block.
Exception:
The parameterized query '(#application_ex_id nvarchar(4000))SELECT E.application_ex_id A' expects the parameter '#application_ex_id', which was not supplied.
Code 1:
command.Parameters.AddWithValue("#application_ex_id", logSearch.LogID);
Code 2:
if (logSearch.LogID != null)
{
command.Parameters.AddWithValue("#application_ex_id", logSearch.LogID);
}
else
{
command.Parameters.AddWithValue("#application_ex_id", DBNull.Value );
}
QUESTION
Can you please explain why it is unable to take NULL from logSearch.LogID value in Code 1 (but able to accept DBNull)?
Is there a better code to handle this?
Reference:
Assign null to a SqlParameter
Datatype returned varies based on data in table
Conversion error from database smallint into C# nullable int
What is the point of DBNull?
CODE
public Collection<Log> GetLogs(LogSearch logSearch)
{
Collection<Log> logs = new Collection<Log>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string commandText = #"SELECT *
FROM Application_Ex E
WHERE (E.application_ex_id = #application_ex_id OR #application_ex_id IS NULL)";
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = System.Data.CommandType.Text;
//Parameter value setting
//command.Parameters.AddWithValue("#application_ex_id", logSearch.LogID);
if (logSearch.LogID != null)
{
command.Parameters.AddWithValue("#application_ex_id", logSearch.LogID);
}
else
{
command.Parameters.AddWithValue("#application_ex_id", DBNull.Value );
}
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
Collection<Object> entityList = new Collection<Object>();
entityList.Add(new Log());
ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader);
for (int i = 0; i < records.Count; i++)
{
Log log = new Log();
Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i];
EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord);
logs.Add(log);
}
}
//reader.Close();
}
}
}
return logs;
}
Annoying, isn't it.
You can use:
command.Parameters.AddWithValue("#application_ex_id",
((object)logSearch.LogID) ?? DBNull.Value);
Or alternatively, use a tool like "dapper", which will do all that messing for you.
For example:
var data = conn.Query<SomeType>(commandText,
new { application_ex_id = logSearch.LogID }).ToList();
I'm tempted to add a method to dapper to get the IDataReader... not really sure yet whether it is a good idea.
I find it easier to just write an extension method for the SqlParameterCollection that handles null values:
public static SqlParameter AddWithNullableValue(
this SqlParameterCollection collection,
string parameterName,
object value)
{
if(value == null)
return collection.AddWithValue(parameterName, DBNull.Value);
else
return collection.AddWithValue(parameterName, value);
}
Then you just call it like:
sqlCommand.Parameters.AddWithNullableValue(key, value);
Just in case you're doing this while calling a stored procedure: I think it's easier to read if you declare a default value on the parameter and add it only when necessary.
SQL:
DECLARE PROCEDURE myprocedure
#myparameter [int] = NULL
AS BEGIN
C#:
int? myvalue = initMyValue();
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue);
some problem, allowed with Necessarily set SQLDbType
command.Parameters.Add("#Name", SqlDbType.NVarChar);
command.Parameters.Value=DBNull.Value
where SqlDbType.NVarChar you type. Necessarily set SQL type.

how to create IDbDataParameter with null-able value?

I have add a null value to parameter list for inserting values to a table, which accepts some null values. Here is my example codes:
bool sql = true;
// ....
List<IDbDataParameter> parameters = new List<IDbDataParmeter>();
// adding values...
object objVal = 1;
parameters.Add(
sql ? new SqlParameter("#colIntA", objVal) :
new OracleParamer(":colIntA", objVal));
// this would not work, what should I add?
objVal = string.Empty;
parameters.Add(
sql ? new SqlParameter("#colIntB", objVal) :
new OracleParamer(":colIntB", objVal));
Not sure if I have use db specific DbNull value and is that also SQL or Oracle specific?
You're trying to assign an empty string ('') to an int parameter there, so yeah, that's not going to work.
To represent a database-independent null value, use DbNull.Value.
new SqlParameter("colIntB", DbNull.Value)
(Note that I've left off the "#", which works in my experience with Sqlparameters. I'm not sure whether you can do the same with the ":" for Oracle.)
One extra tip: Use your connection to create the command, and the command to create the parameters. That will create instances of the right class depending on the type of the underlying connection:
IDbConnection conn = sql ? new SqlConnection(...) : new OracleConnection(...);
// this will give you either an SqlCommand or an OracleCommand
IDbCommand cmd = conn.CreateCommand();
// this will give you either an SqlParameter or an OracleParameter
IDbDataParameter param1 = cmd.CreateParameter();
param1.ParameterName = "colIntB";
param1.Value = objVal;
cmd.Parameters.Add(param1);
Use DbNull.Value. That will work for any ADO.NET-compatible data source (both SQL and Oracle providers), as it is the responsibility of the provider to know what to do when it encounters a DbNull value.

Categories

Resources