C# and SQL Server 2008 : how to handle null from database - c#

I am selecting max(id) from database which are grouped by date. Sometimes there might be situation where date does not have any id. That time it rising error so how to handle it n assign to int variable.
SqlCommand maxid = new SqlCommand("select max(block) from blocks_allocation where date='" + DR.ItemArray.GetValue(7).ToString() + "'", con);
SqlDataReader maxrd = maxid.ExecuteReader();
if (maxrd.Read())
block_no = int.Parse(maxrd["block"].ToString()) + 1;
maxrd.Close();

SqlCommand returns DBNull.Value if the value is null, so if you have a query that could return null values you need to test against DBNull.Value first, like this:
var date = DR.ItemArray.GetValue(7).ToString();
const string sql = "SELECT MAX(block) FROM blocks_allocation WHERE date = #date";
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.AddWithValue("#date", date);
var maxBlock = cmd.ExecuteScalar();
block_no = maxBlock == DBNull.Value ? null : (int?) maxBlock;
}
(This assumes that block_no is a nullable int). I've also changed a few other things:
If q query returns a single value you can use ExecuteScalar instead of Read etc...
You should use using blocks instead of manually closing / disposing of objects.
You shouldn't build dynamic SQL as it can lead to SQL Injection - I've modified the query to use a parametrized query instead.
I've used the inline-if syntax to set block_no, but you can also use a standard if should you prefer:
if (maxBlock == DBNull.Value)
{
block_no = null;
}
else
{
block_no = (int?) maxBlock;
}

Check whether the max(id) is null, if it so then return 1 using ISNULL()
select isnull(max(block),1) from blocks_allocation

Related

Comparing SQL Server DATETIME with DateTime.NOW in C# / ASP.NET

How do I compare a SQL Server DATETIME with the DateTime.Now value? As you can see I assigned it to a Session and tried comparing it with DateTime.Now.
string timestamp = #"SELECT sr.*, ud.* FROM SuspensionRecord sr, UserData ud WHERE sr.User_ID=#User_ID AND ud.User_ID=#User_ID";
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.AddWithValue("#User_ID", Session["UserID"].ToString());
using (SqlDataReader dr = cmd2.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
Session["suspensiondate"] = dr["End_Date_Suspension"].ToString();
}
if (Convert.ToDateTime(Session["supensiondate"]) >= DateTime.Now.Date)
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}
}
}
You should pass in the date and do the comparison in the query instead of in c#. That is one less step. If you do want to do it in c# then use the appropriate types, do not convert the DateTime to a string and then convert it back again.
There is no need for the join (2nd table) in your query
You do not have to use a DataReader for this, you can use ExecuteScalar which returns 1 value instead.
Use Add so you can specify the correct schema types with SqlDbType and not AddWithValue
string timestamp = #"SELECT 1 FROM SuspensionRecord sr WHERE sr.User_ID = #User_ID AND supensiondate > #now";
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.Add("#User_ID", SqlDbType.Int).Value = Session["UserID"]; // do not convert to string
cmd2.Parameters.Add("#now", SqlDbType.DateTime).Value = DateTime.Now.Date;
var result = cmd2.ExecuteScalar();
if(result != null) // if null then there were no records so account is not suspended
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}
First, your SQL is terrible.
You are returning way too much data, and you are using an implicit join (when explicit joins are a part of ANSI-SQL for almost 30 years now!)
Second, Can we stop using AddWithValue() already?
Instead of all this code you can do the entire test on SQL and return a single value:
string sql =
#"SELECT CASE WHEN EXISTS
(
SELECT 1
FROM SuspensionRecord
WHERE User_ID = #User_ID
AND End_Date_Suspension >= CAST(GETDATE() AS DATE)
) THEN 1 ELSE 0 END";
Then you can use ExecuteScalar instead of ExecuteReader, and you don't need to loop through all the irrelevant data:
using (SqlCommand cmd2 = new SqlCommand(timestamp, con))
{
cmd2.Parameters.Add("#User_ID", SqlDbType.Int).Value = Session["UserID"];
if ((int)cmd2.ExecuteScalar() == 1)
{
lblMessage.Text = "The account's status is suspended.";
lblMessage.Visible = true;
}
}

Return SUM SQL Statement, C#, NULL

If the query returns null the goal is to get it to return 0, else return the number. The SUM statement returns the sum of the column values in column ConcurrentUsers.
The code below returns a casting error:
Specified cast is not valid.
It could be because the query is returning a null and is having trouble converting it to int.
Below is the attempt.
Please edit question if anything should be clarified.
SQL query:
string query = #"SELECT SUM(CAST(ConcurrentUsers AS INT))
FROM [website].[db]
WHERE(ConcurrencyLicensing NOT LIKE 0)";
Return value:
SqlConnection conn = new SqlConnection(entityBuilder.ProviderConnectionString);
SqlCommand cmd = new SqlCommand(query, conn);
try
{
conn.Open();
object userNameObj = cmd.ExecuteScalar();
if(userNameObj != null)
{
int getUserName = (int)userNameObj;
return getUserName;
}
else
{
return 0;
}
}
finally
{
conn.Close();
}
Did you try COALESCE ?
string query = #"SELECT COALESCE(SUM(CAST(ConcurrentUsers AS INT)), 0) FROM [website].[db]
WHERE(ConcurrencyLicensing NOT LIKE 0)";
https://msdn.microsoft.com/en-us/library/ms190349.aspx
Evaluates the arguments in order and returns the current value of the first expression that initially does not evaluate to NULL.

Where there is no data printed in this sql command query?

Purpose
I want to print all the rows in my database table Orders where the PrintTime field value is NULL
Code
class Printing
{
public static void check()
{
SqlConnection con = getConnectionString();
string query = "SELECT * FROM Orders WHERE PrintTime = #printTimeValue";
SqlCommand command = new SqlCommand(query, con);
command.Parameters.AddWithValue("#printTimeValue", DBNull.Value);
DataTable results = new DataTable();
using (con)
using (command)
using (SqlDataAdapter dataAdapter = new SqlDataAdapter(command))
dataAdapter.Fill(results);
for (int i = 0; i < results.Rows.Count; i++)
{
Console.WriteLine(results.Rows[i]["ID"].ToString());
Console.WriteLine("---------------");
}
}
private static SqlConnection getConnectionString()
{
string vmpstring =
ConfigurationManager.ConnectionStrings["chinese"].ConnectionString;
SqlConnection vmpsqlcon = new SqlConnection(vmpstring);
return vmpsqlcon;
}
}
and I call it like this:
Printing.check();
Problem
As you see, there is a printing statement, which is
Console.WriteLine(results.Rows[i]["ID"].ToString());
but I don't get any thing printed in the console, though I can see the rows in my database, full of data that its PrintTimecolumn is NULL
Question
what wrong did I do please?
null is not a value but a marker stating that the rdbms has no clue of the value in that field; you cannot check for null using '=' because the equals operator is for values.
in your sql you have to check for null using WHERE PrintTime is null.
beware that if you replace the c# DBNull.Value with an actual value then the 'is' operator is not valid anymore.
a possible workaround that can handle both null and values:
SELECT *
FROM Orders
WHERE PrintTime = #printTimeValue
or (
#printTimeValue is null
and PrintTime is null
)

How to validate the MAX value of the table?

query = "SELECT MAX([Date]) FROM [Events]";
DataTable dt = execute(query);
DateTime date;
if (dt!= null && dt.Rows.Count != 0)
{
date = (DateTime) dt.Rows[0][0];
}
else
{
date = DateTime.Now;
}
now what is my question, when the table Events is empty, it returns me some invalid value, which is not even null...how can i write a normal validation for it?
The value is probably DBNull.Value, you could check for that, but out of the box, you could adapt the query (Assuming sql server): SELECT isnull(MAX([Date]),getdate()) FROM [Events]
That way, the value returned is always a valid datetime and the check can be omitted
SqlCommand cmd=new SqlCommand("SELECT MAX([Date]) FROM [Events]",ConnectionObject);
int _value = cmd.ExecuteScalar();
while(_value!=0)
{
//do something
_value--;
}

ExecuteScalar if DBNull issue

I was trying to handle DbNull exception like this:
string sql_com_sumcastka = "SELECT SUM(price) AS sumprice FROM kliplat WHERE akce='" + zakce.Text + "' AND year=" + year;
SqlCommand sc2 = new SqlCommand(sql_com_sumprice, spojeni);
spojeni.Open();
if (sc2 != DBNull.Value)
{
int result = Convert.ToInt32(sc2.ExecuteScalar());
}
else
{
int result = 0;
}
spojeni.Close();
string sql_com_update_sum = "UPDATE zajezd SET s_prijmy=#s_prijmy WHERE akce='"+zakce.Text+"' AND year="+year;
SqlCommand sc3 = new SqlCommand(sql_com_update_sum,spojeni);
sc3.Parameters.AddWithValue("#s_prijmy", result );
spojeni.Open();
sc3.ExecuteNonQuery();
spojeni.Close();
But as I don't know how to properly handle if result is DBNull I get this erros: Operator '"=' cannot be applied to operands of type system.Data.SqlClient.SqlCommand and System.Dbnull
and
The name 'result' does not exist in the current context
My problem is this line of code:
if (sc2 != DBNull.Value)
{
int result = Convert.ToInt32(sc2.ExecuteScalar());
}
else
{
int result = 0;
}
Thanks for helping.
ExecuteScalar doesn't return DBNull (unless..., please read comments below) but null and you need to test the return value of ExecuteScalar not the SqlCommand that executes the command
int sumOfPrice = 0;
object result = sc2.ExecuteScalar();
if(result != null)
sumOfPrice = Convert.ToInt32(result);
From MSDN
ExecuteScalar returns 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.
As a side note, do not use string concatenation to build a command text to pass to your database. You risk Sql Injection and parsing erroros. Use instead a parameterized query like this
string sql_com_sumcastka = "SELECT SUM(price) AS sumprice FROM kliplat " +
"WHERE akce=#zak AND year=#year";
SqlCommand sc2 = new SqlCommand(sql_com_sumprice, spojeni);
sc2.Parameters.AddWithValue("#zak", zakce.Text);
sc2.Parameters.AddWithValue("#year", year);
Here is the correct way to do that
var objResult = sc2.ExecuteScalar();
if (objResult != DBNull.Value && objResult != null )
{
int result = (int)objResult; //you can just do a normal cast, "SUM(X)" returns a int.
}
else
{
int result = 0;
}
A SqlCommand can never be compared to DBNull.Value in your example. What it sounds like you want is to check the result of your execute scalar invocation to see if that is null:
var result = sc2.ExecuteScalar();
if(result as DBNull == null)
{
// value is not null, do processing
}
I know the answer is late but this is the simplest answer that I have found
SELECT (SUM(price),0) FROM kliplat
If the result is null it will be replaced with 0

Categories