I couldn't find best solution when DateTime value is NULL.
I use this techinque When binding;
_ACTIVATION_DATE = dt.Rows[0]["ACTIVATION_DATE"] == DBNull.Value ? new DateTime(1970, 12, 30) : (DateTime?)dt.Rows[0]["ACTIVATION_DATE"];
When Inserting;
public void Insert()
{
string ad="";
string dd="";
if (ACTIVATION_DATE == null)
ad = "null";
else
ad = "'" + ACTIVATION_DATE + "'";
if (DEACTIVATION_DATE == null)
dd = "null";
else
dd = "'" +DEACTIVATION_DATE +"'";
string sSQL = "INSERT INTO LINE_INFO (ACTIVATION_DATE,DEACTIVATION_DATE,STATUS,PO,NOTES) VALUES (" + ad + "," + dd + "," + _STATUS.ToString() + "," + _PO.ToString() + ",'" + _NOTES.ToString() + "');SELECT ##IDENTITY AS LASTID";
}
Variables;
DateTime? ACTIVATION_DATE;
DateTime? DEACTIVATION_DATE;
What is the smart way to handle Null DateTime values?
When I find the solution I will write an article about this topic.
Why are you using new DateTime(1970, 12, 30) when you're already using a nullable DateTime? The whole point of nullable value types is that you don't need magic values like that.
I would possibly use:
_ACTIVATION_DATE = dt.Rows[0]["ACTIVATION_DATE"] as DateTime?;
That will automatically use the null value for any non-DateTime value. Of course, that means you'll get a null value instead of an exception if you accidentally have an integer or something like that. Alternatively:
object tmp = dt.Rows[0]["ACTIVATION_DATE"];
_ACTIVATION_DATE = tmp is DbNull ? null : (DateTime?) tmp;
Then for the insert statement, do not include values directly in your SQL. Use a parameterized insert statement, and then you can just use a null DateTime? value to insert a null value. No need to mess around with string formats.
DateTime? implies you're using a Nullable<DateTime> to store the value - so why not just use .HasValue and .Value?
You shouldn't insert values directly because you create possibility to SQL injections. Instead you should use parameterized queries:
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "INSERT INTO table1 (column1, column2) VALUES (#param1, #param2)";
command.Parameters.Add("#param1", SqlDbType.DateTime).Value =
DateTime.TryParse(txtDate.Text, out d) ?
(object)d :
DBNull.Value // inserting NULL
...
connection.Open();
command.ExecuteNonQuery();
}
When binding:
object date = reader["date"]; // NULL or '2010-08-26'
txtDate.Text = Convert.IsDBNull(date) ? (DateTime)date : String.Empty;
// or
txtDate.Text = (reader["date"] as DateTime? ?? String.Empty).ToString();
The null handling i most cases depend on the business needs, in your case seams that You need to store some value, but the information that date is null sometimes is useful. Because something has not happened yet. So its hard to determine some good approach to null date handling.
In Your case what it could be done i to replace that new DateTime(1970, 12, 30) with a static const field called default date.
public const DateTime DEFAULT_DATE = new DateTime(1970,12,30);
public void Insert()
{
string activationDate = "null";
string deactivationDate= "null";
if (ACTIVATION_DATE != null) {
ad = string.format("'{0}'",ACTIVATION_DATE); //Hire should be some date format used
}
if (DEACTIVATION_DATE != null) {
ad = string.format("'{0}'",DEACTIVATION_DATE); //Hire should be some date format used
}
string sSQL = string.format("INSERT INTO LINE_INFO (ACTIVATION_DATE,DEACTIVATION_DATE,STATUS,PO,NOTES) VALUES ({0},{1},{2},{3},'{4}');SELECT ##IDENTITY AS LASTID",activationDate ,deactivationDate ,_STATUS,_PO,_NOTES);
Ps. You should not use this type of statement creation instead of this you should use SqlCommand and paramteres
Related
I'm performing a simple SELECT statement and I'm trying to return the value from a DateTime column from a SQL Server 2012 table. The problem is that when I return a NULL DateTime value I don't know how to manage this with my code below.
dtTrainingEnd = (DateTime)reader["TrainingEnd"];
I've searched for the last few days on an answer and cannot find something that will help me. I've found similar posts but still I cannot figure out how they can help me. Can you please explain how I can check to see if the datetime value returned from the database is NULL?
SqlConnection connRead = new SqlConnection(connReadString);
SqlCommand comm = new SqlCommand();
SqlDataReader reader;
string sql;
DateTime dtTrainingEnd = DateTime.Now;
int iTrainingSwipeID = 123;
sql = "SELECT TrainingEnd FROM TrainingSwipe WHERE TrainingSwipeID = " + iTrainingSwipeID;
comm.CommandText = sql;
comm.CommandType = CommandType.Text;
comm.Connection = connRead;
connRead.Open();
reader = comm.ExecuteReader();
while (reader.Read())
{
dtTrainingEnd = (DateTime)reader["TrainingEnd"];
}
connRead.Close();
If it might be null, you could use a nullable type... in this case, a DateTime? type:
while (reader.Read())
{
dtTrainingEnd = ((DateTime?)reader["TrainingEnd"]) ?? some_default_date;
}
connRead.Close();
Or just test for null if you'd rather do that:
while (reader.Read())
{
var endDate = reader["TrainingEnd"];
dtTrainingEnd = (endDate == null) ? some_default_date : (DateTime)endDate;
}
connRead.Close();
In both cases above, I assumed you want dtTrainingEnd to contain something if the date is NULL in the database, so some_default_date is some default DateTime.
Or if you want to leave dtTrainingEnd alone if the value is NULL, then just don't set it in that case:
while (reader.Read())
{
if ((reader["TrainingEnd"]) != null)
dtTrainingEnd = (DateTime)reader["TrainingEnd"];
}
connRead.Close();
*** Depending on how you connect to your db, you may have to replace null with DBNull.Value
With SQL you can do SELECT Coalesce(TrainingEnd,0) and if it is null, you would have a 1900-01-01 date...
I am trying to stop the default value date "01/01/1900"to be entered in the table when the value of the textbox is null.I don't need validation on the form null textbox is ok
Thanks
using (SqlConnection con = new SqlConnection(WebConfigurationManager
.ConnectionStrings["Molecular"].ConnectionString))
{
con.Open();
using (SqlCommand sc = new SqlCommand(#"Insert into ClinicalFollowUp (MBID, Diagnosis,
DateLastSeen, DateofDeath ) values(#MBID, Upper(#Diagnosis),
Convert (date, #DateLastSeen , 103), Convert (date, #DODeath, 103);", con))
{
sc.Parameters.AddWithValue("#MBID", txtMBID1.Text);
sc.Parameters.AddWithValue("#Diagnosis", txtDiagnosis.Text);
// Date Textbox
sc.Parameters.AddWithValue("#DateLastSeen", txtDateLastSeen.Text);
// Date Textbox
sc.Parameters.AddWithValue("#DODeath", txtDateDeath.Text);
}
con.close();
}
I'd do it this way, personally.
static public object ToDbNullableDate(this string s)
{
DateTime d;
var ok = DateTime.TryParse(s, out d);
return ok ? d : DbNull.Value;
}
Then in your code:
sc.Parameters.AddWithValue("#DateLastSeen", txtDateLastSeen.Text.ToDbNullableDate());
You should send the parameters in your command using
The correct data type (NOT as string and do not convert them in Sql Server!)
Specify the data type of the parameter
Specify the length of parameter data types where appropriate. I guessed at your string lengths in the schema, update it accordingly.
Execute the conversion as early as possible in your call stack. Ideally you have a control that is a datetime picker, maybe this can do the conversion for you OR if its a web api then let the serializer deserialize the request to the approriate types.
const string sqlStatement = #"Insert into ClinicalFollowUp (MBID, Diagnosis, DateLastSeen, DateofDeath )
VALUES(#MBID, #Diagnosis , #DateLastSeen, #DODeath);"
using (SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["Molecular"].ConnectionString))
using (SqlCommand sc = new SqlCommand( , con))
{
con.Open();
sc.Parameters.Add(new SqlParameter("#MBID", SqlDbType.VarChar, 100){Value = txtMBID1.Text});
sc.Parameters.Add(new SqlParameter("#Diagnosis", SqlDbType.VarChar, 2000){Value = txtDiagnosis.Text.ToUpper()});
// Date Textbox
sc.Parameters.Add(new SqlParameter("#DateLastSeen", SqlDbType.DateTime){Value = getSqlDate(txtDateLastSeen.Text)});
// Date Textbox
sc.Parameters.Add(new SqlParameter("#DODeath", SqlDbType.DateTime){Value = getSqlDate(txtDateDeath.Text)});
sc.ExecuteNonQuery();
}
// TO DO - validate culture information
public static object getSqlDate(string dateTime)
{
DateTime dt;
return !string.IsNullOrEmpty(dateTime) && DateTime.TryParse(dateTime, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt)
? (object) dt
: (object) System.DBNull.Value;
}
try like this:
if (string.IsNullOrWhiteSpace(txtDateLastSeen.Text)
{
sc.Parameters.AddWithValue("#DateLastSeen", DbNull.Value);
}
else
{
sc.Parameters.AddWithValue("#DateLastSeen", txtDateLastSeen.Text);
}
EDIT: IsNullOrWhiteSpace, as suggested, is a bit simpler.
I am trying to get the result of sql query in an int variable, but I am getting object null reference error. Can someone guide me please.
oconn = new SqlConnection(oSession.CONNECTION_STRING);
oconn.Open();
objCmd.CommandText = "select Rule_Approval_Selection from UserFile where uid=" + intUserID;
int value = (Int32)(objCmd.ExecuteScalar());
oconn.Close();
ExecuteScalar() returns null when the command has no rows. In your case, when intUserId does not correspond to an existing user, null would be returned.
Switch to int? to handle this issue:
int? value = (Int32?)(objCmd.ExecuteScalar());
Now your variable value would be set to non-null when intUserId exists in the database; otherwise, it would be null.
oconn = new SqlConnection(oSession.CONNECTION_STRING);
oconn.Open();
objCmd.CommandText = "select Rule_Approval_Selection from UserFile where uid=" + intUserID;
var x=objCmd.ExecuteScallar();
if (x!= null && DBNull.Value != x)
{
int value = (Int32)(objCmd.ExecuteScalar());
}
oconn.Close();
try this...
I have a C# DateTime class and wanted to know how I need to format it in a SQL Server CE query to insert it into the database, I was hoping to have both the date and time inserted in. Currently when I try variations thereof I get invalid format exceptions.
Current format I'm using is: dd/MM/yyyy, was hoping to do something like dd/MM/yyyy hh:mm:ss.
The way I'm trying to do the insert is like so:
( ( DateTime )_Value ).ToString( "dd/MM/yyyy hh:mm:ss" )
Obviously hh:mm:ss isn't working, if that isn't there dd/MM/yyyy executes successfully in the query.
I've tried a few formats including what I've found on google but none have worked so far...
If you're worried about getting the format right at all, something has already gone seriously wrong. There are two things you need to do to correctly work with datetime values in any database, not just sqlce:
Make sure you're using a datetime type for the column (not a text type like varchar)
Make sure you're using a datetime parameter in a parameterized query, and not string concatenation.
If you do that, there is no formatting involved on your part. At all. Example:
void SetDate(int recordID, DateTime timeStamp)
{
string SQL = "UPDATE [sometable] SET someDateTimeColumn= #NewTime WHERE ID= #ID";
using (var cn = new SqlCeConnection("connection string here"))
using (var cmd = new SqlCeCommand(SQL, cn))
{
cmd.Parameters.Add("#NewTime", SqlDbType.DateTime).Value = timeStamp;
cmd.Parameters.Add("#ID", SqlDbType.Integer).Value = recordID;
cn.Open();
cmd.ExecuteNonQuery();
}
}
Never ever ever ever EVER use string manipulation to substitute values into sql queries. It's a huge no-no.
Try the following format:
DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")
Man, you do not need to convert string to DateTime.
Use a instance of a new DateTime and pass the date as parameter. Like this:
using (var ctx = new DBPreparoEntities())
{
var _client = from p in ctx.Client
select new Client
{
data = new DateTime(2016,08,17),
dateconf = null,
scod_cli = p.Rua,
valorini = 7214.62m,
};
return client.ToList();
}
don't use:
... data = DateTime.Parse("2016/12/10") // or other type convertions.
private void button1_Click(object sender, EventArgs e)
{
var cnn1 ="";//connection string
SqlCeConnection cnn = new SqlCeConnection(cnn1);
datetime dt4 = DateTime.Today.Date.ToString("yyyyMMdd").trim();//format
var qry ="insert into tbl_test(User_Id, DateOfJoin)values (11,'" + dt4 + "')";
cmd = new SqlCeCommand(qry, cnn);
try
{
dr = cmd.ExecuteReader();
}
catch (Exception ex)
{
string sr = ex.Message;
throw;
}
}
Above code worked for me.
sorry this is in vb.net, but this is a method i use to convert from a CE date/time format:
Public Shared Function ConvertSqlDateTimeFormat(ByVal s As String) As String
Dim theDate As New Text.StringBuilder
Dim sTemp As String = ""
Dim iIndex As Integer
If s.Length > 8 Then
'first we do the time
iIndex = s.IndexOf(" ", System.StringComparison.OrdinalIgnoreCase)
If iIndex > 0 Then
sTemp = s.Substring(iIndex).Trim
iIndex = sTemp.IndexOf(".", System.StringComparison.OrdinalIgnoreCase)
If iIndex > 0 Then
sTemp = sTemp.Substring(0, iIndex)
End If
End If
'next the date
theDate.Append(s.Substring(4, 2))
theDate.Append("/")
theDate.Append(s.Substring(6, 2))
theDate.Append("/")
theDate.Append(s.Substring(0, 4))
theDate.Append(" ")
theDate.Append(sTemp)
End If
Return theDate.ToString
End Function
I am using the following SQL query and the ExecuteScalar() method to fetch data from an Oracle database:
sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();
It is showing me this error message:
System.NullReferenceException: Object reference not set to an instance of an object
This error occurs when there is no row in the database table for userid=2.
How should I handle this situation?
According to MSDN documentation for DbCommand.ExecuteScalar:
If the first column of the first row in the result set is not found, a
null reference (Nothing in Visual Basic) is returned. If the value in
the database is null, the query returns DBNull.Value.
Consider the following snippet:
using (var conn = new OracleConnection(...)) {
conn.Open();
var command = conn.CreateCommand();
command.CommandText = "select username from usermst where userid=2";
string getusername = (string)command.ExecuteScalar();
}
At run-time (tested under ODP.NET but should be the same under any ADO.NET provider), it behaves like this:
If the row does not exist, the result of command.ExecuteScalar() is null, which is then casted to a null string and assigned to getusername.
If the row exists, but has NULL in username (is this even possible in your DB?), the result of command.ExecuteScalar() is DBNull.Value, resulting in an InvalidCastException.
In any case, the NullReferenceException should not be possible, so your problem probably lies elsewhere.
First you should ensure that your command object is not null. Then you should set the CommandText property of the command to your sql query. Finally you should store the return value in an object variable and check if it is null before using it:
command = new OracleCommand(connection)
command.CommandText = sql
object userNameObj = command.ExecuteScalar()
if (userNameObj != null)
string getUserName = userNameObj.ToString()
...
I'm not sure about the VB syntax but you get the idea.
I just used this:
int? ReadTerminalID()
{
int? terminalID = null;
using (FbConnection conn = connManager.CreateFbConnection())
{
conn.Open();
FbCommand fbCommand = conn.CreateCommand();
fbCommand.CommandText = "SPSYNCGETIDTERMINAL";
fbCommand.CommandType = CommandType.StoredProcedure;
object result = fbCommand.ExecuteScalar(); // ExecuteScalar fails on null
if (result.GetType() != typeof(DBNull))
{
terminalID = (int?)result;
}
}
return terminalID;
}
The following line:
string getusername = command.ExecuteScalar();
... will try to implicitly convert the result to string, like below:
string getusername = (string)command.ExecuteScalar();
The regular casting operator will fail if the object is null.
Try using the as-operator, like this:
string getusername = command.ExecuteScalar() as string;
sql = "select username from usermst where userid=2"
var _getusername = command.ExecuteScalar();
if(_getusername != DBNull.Value)
{
getusername = _getusername.ToString();
}
Check out the example below:
using System;
using System.Data;
using System.Data.SqlClient;
class ExecuteScalar
{
public static void Main()
{
SqlConnection mySqlConnection =new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;");
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText ="SELECT COUNT(*) FROM Employee";
mySqlConnection.Open();
int returnValue = (int) mySqlCommand.ExecuteScalar();
Console.WriteLine("mySqlCommand.ExecuteScalar() = " + returnValue);
mySqlConnection.Close();
}
}
from this here
SQL NULL value
equivalent in C# is DBNull.Value
if a NULLABLE column has no value, this is what is returned
comparison in SQL: IF ( value IS NULL )
comparison in C#: if (obj == DBNull.Value)
visually represented in C# Quick-Watch as {}
Best practice when reading from a data reader:
var reader = cmd.ExecuteReader();
...
var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString());
In my experience, there are some cases the returned value can be missing and thus execution fails by returning null. An example would be
select MAX(ID) from <table name> where <impossible condition>
The above script cannot find anything to find a MAX in. So it fails. In these such cases we must compare the old fashion way (compare with C# null)
var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));
If you either want the string or an empty string in case something is null, without anything can break:
using (var cmd = new OdbcCommand(cmdText, connection))
{
var result = string.Empty;
var scalar = cmd.ExecuteScalar();
if (scalar != DBNull.Value) // Case where the DB value is null
{
result = Convert.ToString(scalar); // Case where the query doesn't return any rows.
// Note: Convert.ToString() returns an empty string if the object is null.
// It doesn't break, like scalar.ToString() would have.
}
return result;
}
Always have a check before reading row.
if (SqlCommand.ExecuteScalar() == null)
{
}
This is the easiest way to do this...
sql = "select username from usermst where userid=2"
object getusername = command.ExecuteScalar();
if (getusername!=null)
{
//do whatever with the value here
//use getusername.toString() to get the value from the query
}
In your case either the record doesn't exist with the userid=2 or it may contain a null value in first column, because if no value is found for the query result used in SQL command, ExecuteScalar() returns null.
Alternatively, you can use DataTable to check if there's any row:
SqlCommand cmd = new SqlCommand("select username from usermst where userid=2", conn);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
string getusername = "";
// assuming userid is unique
if (dt.Rows.Count > 0)
getusername = dt.Rows[0]["username"].ToString();
private static string GetUserNameById(string sId, string connStr)
{
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
System.Data.SqlClient.SqlCommand command;
try
{
// To be Assigned with Return value from DB
object getusername;
command = new System.Data.SqlClient.SqlCommand();
command.CommandText = "Select userName from [User] where userid = #userid";
command.Parameters.AddWithValue("#userid", sId);
command.CommandType = CommandType.Text;
conn.Open();
command.Connection = conn;
//Execute
getusername = command.ExecuteScalar();
//check for null due to non existent value in db and return default empty string
string UserName = getusername == null ? string.Empty : getusername.ToString();
return UserName;
}
catch (Exception ex)
{
throw new Exception("Could not get username", ex);
}
finally
{
conn.Close();
}
}
Slight conjecture: if you check the stack for the exception, it is being thrown then the ADO.NET provider for Oracle is reading the underlying rowset to get the first value.
If there is no row, then there is no value to find.
To handle this case execute for a reader and handle Next() returning false for the case of no match.
I Use it Like This with Microsoft Application Block DLL (Its a help library for DAL operations)
public string getCopay(string PatientID)
{
string sqlStr = "select ISNULL(Copay,'') Copay from Test where patient_id=" + PatientID ;
string strCopay = (string)SqlHelper.ExecuteScalar(CommonCS.ConnectionString, CommandType.Text, sqlStr);
if (String.IsNullOrEmpty(strCopay))
return "";
else
return strCopay ;
}
I have seen in VS2010
string getusername = command.ExecuteScalar();
gives compilation error,
Cannot implicitly convert type object to string.
So you need to write
string getusername = command.ExecuteScalar().ToString();
when there is no record found in database it gives error
Object reference not set to an instance of an object
and when I comment '.ToString()', it is not give any error. So I can say ExecuteScalar not throw an exception. I think anserwer given by #Rune Grimstad is right.
I had this issue when the user connecting to the database had CONNECT permissions, but no permissions to read from the database. In my case, I could not even do something like this:
object userNameObj = command.ExecuteScalar()
Putting this in a try/catch (which you should probably be doing anyway) was the only way I could see to handle the insufficient permission issue.
object objUserName;
objUserName = command.ExecuteScalar();
if (objUserName == null) //if record not found ExecuteScalar returns null
{
return "";
}
else
{
if (objUserName == DBNull.Value) //if record found but value in record field is null
{
return "";
}
else
{
string getusername = objUserName.ToString();
return getusername;
}
}
/* Select some int which does not exist */
int x = ((int)(SQL_Cmd.ExecuteScalar() ?? 0));
I used this in my vb code for the return value of a function:
If obj <> Nothing Then
Return obj.ToString()
Else
Return ""
End If
Try this code, it appears to solve your problem.
Dim MaxID As Integer = Convert.ToInt32(IIf(IsDBNull(cmd.ExecuteScalar()), 1, cmd.ExecuteScalar()))
I'm using Oracle.
If your sql returns numeric value, which is int, you need to use Convert.ToInt32(object). Here is the example below:
public int GetUsersCount(int userId)
{
using (var conn = new OracleConnection(...)){
conn.Open();
using(var command = conn.CreateCommand()){
command.CommandText = "select count(*) from users where userid = :userId";
command.AddParameter(":userId", userId);
var rowCount = command.ExecuteScalar();
return rowCount == null ? 0 : Convert.ToInt32(rowCount);
}
}
}
Try this
sql = "select username from usermst where userid=2"
string getusername = Convert.ToString(command.ExecuteScalar());