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
)
Related
I'm using stored procedure to get the 'password' value from the database. and i need to assign this value to a variable. I'm using asp.net- mvc and Ado.net.
Here is my stored procedure.
CREATE PROCEDURE [dbo].[getPassword]
(
#Email VARCHAR(100)
)
AS
BEGIN
SELECT Password FROM dbo.Staff_Login WHERE Email=#Email
END
Here is my repository class.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
namespace Job_Recuitment_System.Repository
{
public class LoginRepository
{
private SqlConnection con;
//To handle sql connection
private void connection() {
string constr = ConfigurationManager.ConnectionStrings["mycon"].ToString();
con = new SqlConnection(constr);
}
//to get the password
public List<StaffLogin> getPassword(StaffLogin obj) {
connection();
List<StaffLogin> pword = new List<StaffLogin>();
SqlCommand com = new SqlCommand("getPassword", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Email",obj.Email);
SqlDataAdapter da = new SqlDataAdapter(com);
DataTable dt = new DataTable();
con.Open();
da.Fill(dt);
con.Close();
//Bind StaffLogin
pword = (from DataRow dr in dt.Rows
select new StaffLogin()
{
Password = Convert.ToString(dr["Password"]),
}).ToList();
return pword;
}
}
}
I have use a list. But i need to assign value to a varible. because i only i need is one value (password).
You don't need an SqlDataAdapter but you just use the SqlCommand.ExecuteScalar
connection();
SqlCommand com = new SqlCommand("getPassword", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add("#Email",SqlDbType.NVarChar, 100). Value = obj.Email;
con.Open();
var result = com.ExecuteScalar();
if(result != null)
MessageBox.Show("Password = " + result.ToString();
con.Close();
ExecuteScalar returns the first column of the first row retrieved by the command and your query fits nicely this condition. However it is important to consider that ExecuteScalar could return NULL if the query doesn't produce any result so always test the result against a null value before using it.
On another matter I really suggest you to avoid stored procedures for these simple menial tasks unless there is a good reason to use them. Using the Add instead of AddWithValue and specifying the exact size of the parameter gives to the Sql optimizer enough hints to create an optimized query.
Finally, remember that storing/returning passwords in clear text is considered a very big security risk. Try to use a safer method as explained in this question: Best way to store passwords in a database
In this case you are retrieving the value of a single column, You can use ExecuteScalar() in such situations. Then the command execution will be like the following:
string passwordStr= (string)com.ExecuteScalar();
So the signature of the getPassword method will also be changed, its return type will become string instead for List<StaffLogin>; the new signature will be:
public string getPassword(StaffLogin obj)
{
connection();
string passwordStr = String.Empty;
using (SqlCommand com = new SqlCommand("getPassword", con))
{
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Email", obj.Email);
passwordStr = (string)com.ExecuteScalar();
}
return passwordStr;
}
First, I did search for this first and found this question answered: Previous Answer
The problem I have with this answer is that using this method causes a NullReferenceException. Obviously the code will still work with a try/catch block, but I had always understood that intentionally using an Exception as a means of controlling flow was poor design. Is there a better method of doing this?
To be clear as to the parameters, I am using OleDbConnection and OleDbCommand to read/write an Access 2010 database (.accdb format).
Below is the code I have currently using the above answer's approach:
public bool ReadAccessDb(string filePath, string queryString, bool hasRecords)
{
string connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source=" + filePath + ";" +
#"User Id=;Password=;";
using (OleDbConnection connection = new OleDbConnection(connectionString))
using (OleDbCommand command = new OleDbCommand(queryString, connection))
{
try
{
connection.Open();
int count = (int)command.ExecuteScalar();
//This works, but if no records exist it uses the Exception system to halt further action. Look for better approach.
if(count > 0)
{
hasRecords = true;
}
}
catch (System.Exception ex)
{
}
}
return hasRecords;
}
You can use :
int count = command.ExecuteScalar() is DBNull ? 0 : Convert.ToInt32(command.ExecuteScalar());
or use :
object obj = command.ExecuteScalar();
int count = obj is DBNull ? 0 : Convert.ToInt32(obj);
I'm posting this answer because the question is a bit ambiguous and the (currently) accepted answer can conceivably be "fooled" if a row exists but the first column returned by the SELECT statement happens to contain a NULL. Consider the test table
CREATE TABLE MyTable (ID COUNTER PRIMARY KEY, NullableColumn INTEGER NULL)
INSERT INTO MyTable (NullableColumn) VALUES (NULL)
which would look like
ID NullableColumn
-- --------------
1 <NULL>
If the SELECT statement used for testing was
string sql = "SELECT NullableColumn FROM MyTable WHERE ID=1";
then the method
static bool RecordExists(string queryString, OleDbConnection conn)
{
bool rtn;
using (var command = new OleDbCommand(queryString, conn))
{
object obj = command.ExecuteScalar();
int count = obj is DBNull ? 0 : Convert.ToInt32(obj);
rtn = (count != 0);
}
return rtn;
}
would return False, whereas this method
static bool RecordExists(string queryString, OleDbConnection conn)
{
bool rtn;
string rowCountString = String.Format("SELECT COUNT(*) AS n FROM ({0})", queryString);
using (var command = new OleDbCommand(rowCountString, conn))
{
int count = (int)command.ExecuteScalar();
rtn = (count != 0);
}
return rtn;
}
would return True.
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
Hi I have the following code which lists all column names for a given SQL table:
public static DataTable GetSQLTableSchema(string _connectionString,string _tableName)
{
string connectionString = _connectionString;
string tableName = _tableName.Trim();
DataTable schemaTable = new DataTable();
SqlDataReader sqlDataReader;
try {
using (SqlConnection connection = new SqlConnection(connectionString))
{
string queryString = "SELECT * FROM " + tableName;
using(SqlCommand queryCMD = new SqlCommand(queryString))
{
queryCMD.Connection = connection;
connection.Open();
sqlDataReader = queryCMD.ExecuteReader(CommandBehavior.KeyInfo);
schemaTable = sqlDataReader.GetSchemaTable();
connection.Close();
}
}
}catch(Exception ex)
{
Console.WriteLine(ex);
}
#region Print Table Schema
foreach(DataRow field in schemaTable.Rows)
{
foreach(DataColumn property in schemaTable.Columns)
{
Console.WriteLine("{0} - {1}",field[0],//HERE!);
}
}
#endregion
return schemaTable;
}
At the line I marked (HERE!) I want to print the column's name and a boolean whether it is allow NULL. But all I get from field is an itemarray[]. I am sure that one of the values the array contains shows the allow NULL value. I can not figure out which one it is. Besides I think there must be a more elegant way.
You can do:
Console.WriteLine(property.ColumnName +" = "+ field[property].ToString());
AllowDBNull Reference:
Gets or sets a value that indicates whether null values are allowed in this column for rows that belong to the table.
DataColumn has an AllowDBNull property.
http://msdn.microsoft.com/en-gb/library/system.data.datacolumn.allowdbnull(v=vs.100).aspx
Assuming the ODBC driver in question is returning the Schema table appropriately, this should give you what you need.
SELECT column_name, is_nullable FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ?
This is a question from an experienced beginner!
Using ASP.NET 4 C# AND SQL server,
I have a connection string in web.config to myDatabase named "myCS".
I have a database named myDB.
I have a table named myTable with a primary key named myPK
What are the NECESSARY lines of code behind (minimal code) to create a SQL connection, then select from myTable where myPK=="simpleText"
it will probably include:
sqlconnection conn = new sqlconnection(??? myCS)
string SQLcommand = select * from myDB.myTable where myPK==myTestString;
sqlCommand command = new SqlCommand(SQL,conn);
conn.Open();
booleanFlag = ????
conn.Close();
conn.Dispose();
then
If ( theAnswer != NULL ) // or (if flag)
{
Response.Redirect("Page1.aspx");
}
else
{
Response.Redirect("Page2.aspx");
}
Here is a limited simple tutorial:
First, you want to have a class to do the hard work for you, then you will use it with ease.
First, you have to crate the connection string in your web.config file and name it.
Here it is named DatabaseConnectionString, but you may named it myCS as required in the question.
Now, in App_Code create a new class file and name it SqlComm (this is just an example name) like:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
public class SqlComm
{
// this is a shortcut for your connection string
static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["dbConStr"].ConnectionString;
// this is for just executing sql command with no value to return
public static void SqlExecute(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
// with this you will be able to return a value
public static object SqlReturn(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
object result = (object)cmd.ExecuteScalar();
return result;
}
}
// with this you can retrieve an entire table or part of it
public static DataTable SqlDataTable(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
DataTable TempTable = new DataTable();
TempTable.Load(cmd.ExecuteReader());
return TempTable;
}
}
// sooner or later you will probably use stored procedures.
// you can use this in order to execute a stored procedure with 1 parameter
// it will work for returning a value or just executing with no returns
public static object SqlStoredProcedure1Param(string StoredProcedure, string PrmName1, object Param1)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(PrmName1, Param1.ToString()));
cmd.Connection.Open();
object obj = new object();
obj = cmd.ExecuteScalar();
return obj;
}
}
}
Okay, this only a class, and now you should know how to use it:
If you wish to execute a command like delete, insert, update etc. use this:
SqlComm.SqlExecute("TRUNCATE TABLE Table1");
but if you need to retrieve a specific value from the database use this:
int myRequiredScalar = 0;
object obj = new object();
obj = SqlComm.SqlReturn("SELECT TOP 1 Col1 FROM Table1");
if (obj != null) myRequiredScalar = (int)obj;
You can retrieve a bunch of rows from the database this way (others like other ways)
This is relevant to your sepecific question
int Col1Value = 0;
DataTable dt = new DataTable();
dt = SqlComm.SqlDataTable("SELECT * FROM myTable WHERE myPK='simpleText'");
if (dt.Rows.Count == 0)
{
// do something if the query return no rows
// you may insert the relevant redirection you asked for
}
else
{
// Get the value of Col1 in the 3rd row (0 is the first row)
Col1Value = (int)dt.Rows[2]["Col1"];
// or just make the other redirection from your question
}
If you need to execute a stored procedure with or without returning a value back this is the way to do that (in this example there are no returning value)
SqlComm.SqlStoredProcedure1Param("TheStoredProcedureName", "TheParameterName", TheParameterValue);
Again, for your specific question return the table using the SqlDataTable , and redirect if dt.Rows.Count >0
Have fun.
There are many ways: LINQ, SqlDataReader, SQLDataAdapter, according to what you want to read (single value, datatable ...), so here is an example:
using (SqlConnection con = new SqlConnection("SomeConnectionString"))
{
var cmd = new SqlCommand("select from myTable where myPK==N'"+ simpleText+ "'",con);
cmd.Connection.Open();
var sqlReader = cmd.ExecuteReader();
while(sqlReader.Read())
{
//Fill some data like : string result = sqlReader("SomeFieldName");
}
sqlReader.Close();
cmd.Connection.Close();
cmd.Dispose();
}