I am using a using statement for validating a customer number.
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
connection.Open();
using (SqlCommand cmdCheck = new SqlCommand("SELECT COUNT(CUSTOMER_NO) FROM WEBSITE_CUSTOMERS WHERE UPPER(CUSTOMER_NO) = '" + strCustomer.Trim().ToUpper() + "';", connection))
{
int nExists = (int)cmdCheck.ExecuteScalar();
if (nExists > 0)
return true;
else
return false;
}
}
This is code previously advised to me on stackoverflow for checking preexisting records... it works great, but I would like to know if there's a way that I can use a parameter with it for the customer number since this variable is entered through the form, I want to protect it from injection. Where would I create the parameter for cmdCheck when its in a using statement like this?
Add the parameter after you've initialized the command. A convenient method is AddWithValue:
const string sql = #"SELECT
COUNT(CUSTOMER_NO)
FROM
WEBSITE_CUSTOMERS
WHERE
UPPER(CUSTOMER_NO) = #CUSTOMER_NO;";
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
using (SqlCommand cmdCheck = new SqlCommand(sql, connection))
{
cmdCheck.Parameters.AddWithValue("#CUSTOMER_NO", strCustomer.Trim().ToUpper());
connection.Open();
int nExists = (int)cmdCheck.ExecuteScalar();
return nExists > 0;
}
}
Related
I have a table TümEnvanter$ which has 2 columns equipment code (Ekipman) and their description (Tanım).
User chooses the equipment from the combo box, and I want the description of the chosen equipment to appear in the label at the time they choose from combobox.
Here is what I tried:
SqlCommand cmdTanim = new SqlCommand("select Tanım from TümEnvanter$ where Ekipman = '" + comboBox_ekipman.Text + "'", connect);
connect.Open();
SqlDataReader reader = cmdTanim.ExecuteReader();
string tanim = reader.ToString();
labelTanim.Text = "Ekipman Tanımı: "+tanim+" ";
When I use this code, I get in the label:
Ekipman Tanımı: System.Data.SqlClient.SqlDataReader
How can I fix this? Thank you.
If you only expect a single value, then ExecuteScalar is much simpler than using a reader, i.e.
labelTanim.Text = Convert.ToString(cmdTanim.ExecuteScalar());
In general, perhaps consider tools like "Dapper" which would make this simple even in multi-row cases and solve the SQL injection problem trivially:
string s = connect.QuerySingle<string>(
"select Tanım from TümEnvanter$ where Ekipman = #val", // command
new { val = comboBox_ekipman.Text }); // parameters
You should try this code, it gathers some good practices, such as:
1) Uses using statement to release unamnaged resources (SQL connections, IDisposables in general).
2) Prevents from SQL injection using Parameters field of SqlCommand object.
Also, I used ExecuteScalar method, mentioned by #MarcGravell, which simplifies the code.
public void SqlConn()
{
string tanim = null;
using (SqlConnection connect = new SqlConnection("connectionString"))
{
using (SqlCommand cmdTanim = new SqlCommand())
{
cmdTanim.Connection = connect;
cmdTanim.CommandText = "select Tanım from TümEnvanter$ where Ekipman = #param";
cmdTanim.Parameters.Add("#param", SqlDbType.VarChar).Value = comboBox_ekipman.Text;
connect.Open();
tanim = (string)cmdTanim.ExecuteScalar();
}
}
labelTanim.Text = "Ekipman Tanımı: " + tanim + " ";
}
Something like this:
// wrap IDisposable into using
using (SqlConnection connect = new SqlConnection("Put_Connection_String_Here"))
{
connect.Open();
// Make SQL readable and parametrized
string sql =
#"select Tanım
from TümEnvanter$
where Ekipman = #prm_Ekipman";
// wrap IDisposable into using
using (SqlCommand cmdTanim = new SqlCommand(sql, connect))
{
//TODO: explicit typing Add(..., DbType...) is a better choice then AddWithValue
cmdTanim.Parameters.AddWithValue("#prm_Ekipman", comboBox_ekipman.Text);
// We want one record only; ExecuteScalar() instead of ExecuteReader()
// String interpolation shortens the code
labelTanim.Text = $"Ekipman Tanımı: {cmdTanim.ExecuteScalar()} ";
}
}
Use this code instead by using the reader() method of SqlDataReader to read and access the contents of the SqlDataReader.
SqlCommand cmdTanim = new SqlCommand("select Tanım from TümEnvanter$ where Ekipman = '" + comboBox_ekipman.Text + "'", connect);
connect.Open();
SqlDataReader reader = cmdTanim.ExecuteReader();
if(reader.HasRows){
reader.read();
string tanim = reader.ToString();
labelTanim.Text = "Ekipman Tanımı: "+tanim+" ";
}
Hope this code snippet works for you.
Use below code :
SqlCommand cmdTanim = new SqlCommand("select Tanım from TümEnvanter$ where Ekipman = '" + comboBox_ekipman.Text + "'", connect);
connect.Open();
SqlDataReader reader = cmdTanim.ExecuteReader();
string tanim = string.Empty;
while (reader.Read())
{
tanim= reader["Tanım"].ToString()
}
labelTanim.Text = "Ekipman Tanımı: "+tanim+" ";
I have this code and it does not work. Does anyone know why?
It did not return any data, but if run the query in SQL Server it returns the data.
using (SqlConnection connection = new SqlConnection(_dbContext.GetConnectionString()))
{
using (SqlCommand command = new SqlCommand())
{
StringBuilder stringQuery = new StringBuilder();
stringQuery.Append(" SELECT cd_material, ds_material");
stringQuery.Append(" FROM tbl_materiais");
stringQuery.Append(" WHERE ds_material like #Name");
command.Parameters.AddWithValue("#Name", "%" + name + "%");
command.CommandText = stringQuery.ToString();
command.CommandType = System.Data.CommandType.Text;
command.Connection = connection;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
_product = new ProductSell();
((IProduct)_product).ID = reader.GetFieldValue<int>(0);
((IProduct)_product).Name = reader.GetFieldValue<string>(1);
listProduct.ToList<IProduct>().Add(_product);
}
}
}
}
What is listProduct and why do you call its ToList<>()?
listProduct.ToList<IProduct>() returns a new instance of List<IProduct> that is forgotten after this line executes. Calling .Add(_product) on this returned list does not affect listProduct.
My problem stay here
while (reader.Read())
{
DoSomething();
}
reader.Read() never is read, my table is simple, have only attributes: cd_material(int), ds_material(varchar). And Exception not are triggered.
This query :
SELECT cd_material, ds_material FROM tbl_materiais WHERE ds_material = '%produto%'
Many rows are returned if in owner database ( sql management)
i want to check weather a user is in my database (checking with the id). i am using the following code. It is working. i just want to know ,is this the right way or is there any other method for doing this better(like using COUNT(*) or any other query). I am doing my project in MVC4
public bool CheckUser(int mem_id)
{
bool flag = false;
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Id FROM Mem_Basic WHERE Id="+ mem_id +"", con))
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
flag = true;
}
}
}
return flag;
}
if you want a single value you can use ExecuteSclar function. and Use parametrized queries to avoid sql injection.
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT 1 FROM Mem_Basic WHERE Id=#id", con))
{
cmd.Parameters.AddWithValue("#ID", yourIDValue);
con.Open();
var found=(int)cmd.ExecuteScalar(); //1 means found
}
}
Yes, your code will be simpler if you use a SELECT COUNT(*) query and assign the single value returned to an int instead of using the reader syntax.
Try this:
public bool CheckUser(int mem_id)
{
bool flag = false;
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Mem_Basic WHERE Id="+ mem_id +""", con))
{
con.Open();
int count = (int) cmd.ExecuteScalar();
if(count > 0)
{
flag = true;
}
}
}
return flag;
}
Instead of using ExecuteReader you can use ExecuteScalar. In my opinion your code will be more clean. See more on MSDN
About your sql query: you can check performance in SQL query analyzer in Managment Studio. See more Where is the Query Analyzer in SQL Server Management Studio 2008 R2? . But in 99% it is optimal.
You could also do something similar to yours but instead just check for null.
public bool CheckUser(int mem_id)
{
bool flag = false;
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Id FROM Mem_Basic WHERE Id="+ mem_id +"", con))
{
con.Open();
if (cmd.ExecuteScalar() != null)
{
flag = true;
}
}
}
}
Alright this is the first method
public static string srConnectionString = "server=localhost;database=myDB; "+
" uid=sa;pwd=myPW;";
And this is the second method
public static string srConnectionString = "server=localhost;database=myDB; "+
" integrated security=SSPI;persist security info=False; Trusted_Connection=Yes;";
Are there any performance difference or any other difference between these 2 connection strings?
Here my sql connection class any suggestion ?
using System;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data;
public static class DbConnection
{
public static string srConnectionString = "server=localhost; database=myDB; uid=sa; pwd=myPW;";
public static DataSet db_Select_Query(string strQuery)
{
DataSet dSet = new DataSet();
if (strQuery.Length < 5)
return dSet;
try
{
using (SqlConnection connection = new SqlConnection(srConnectionString))
{
connection.Open();
using (SqlDataAdapter DA = new SqlDataAdapter(strQuery, connection))
{
DA.Fill(dSet);
}
}
return dSet;
}
catch
{
using (SqlConnection connection = new SqlConnection(srConnectionString))
{
if (srConnectionString.IndexOf("select Id from tblAspErrors") != -1)
{
connection.Open();
strQuery = strQuery.Replace("'", "''");
using (SqlCommand command = new SqlCommand("insert into tblSqlErrors values ('" + strQuery + "')", connection))
{
command.ExecuteNonQuery();
}
}
}
return dSet;
}
}
public static void db_Update_Delete_Query(string strQuery)
{
if (strQuery.Length < 5)
return;
try
{
using (SqlConnection connection = new SqlConnection(srConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(strQuery, connection))
{
command.ExecuteNonQuery();
}
}
}
catch
{
strQuery = strQuery.Replace("'", "''");
using (SqlConnection connection = new SqlConnection(srConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("insert into tblSqlErrors values ('" + strQuery + "')", connection))
{
command.ExecuteNonQuery();
}
}
}
}
}
The performance difference is insignificantly small that it can be ignored. The authentication checks are
...performed only on login. The connection is not rechecked for each query. However with connection pooling, the connection is authenticated and reset many times, quite possibly for nearly every query
...the same as every file access and other activity involving the domain getting checked against Active Directory
FYI these two settings are the same (use one or the other):
integrated security=SSPI
Trusted_Connection=Yes
In some programming contexts getting a scalar value from a sql query is easy:
RowCount = Connection.Execute("SELECT Count(*) FROM TableA").Fields(0).Value
In C#, given a SqlConnection variable conn that is already open, is there a simpler way to do this same thing without laboriously creating a SqlCommand, a DataReader, and all in all taking about 5 lines to do the job?
SqlCommand has an ExecuteScalar method that does what you want.
cmd.CommandText = "SELECT COUNT(*) FROM dbo.region";
Int32 count = (Int32) cmd.ExecuteScalar();
If you can use LINQ2SQL (or EntityFramework) you can simplify the actual query asking to
using (var context = new MyDbContext("connectionString"))
{
var rowCount = context.TableAs.Count();
}
If LINQ2SQL is an option that has lots of other benefits too compared to manually creating all SqlCommands, etc.
There is ExecuteScalar which saves you at least from the DataReader:
static public int AddProductCategory(string newName, string connString)
{
Int32 newProdID = 0;
string sql =
"INSERT INTO Production.ProductCategory (Name) VALUES (#Name); "
+ "SELECT CAST(scope_identity() AS int)";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.Add("#Name", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = newName;
try
{
conn.Open();
newProdID = (Int32)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return (int)newProdID;
}
(Example taken from this MSDN documentation article)
You do not need a DataReader. This example pulls back the scalar value:
Object result;
using (SqlConnection con = new SqlConnection(ConnectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand(SQLStoredProcName, con)) {
result = cmd.ExecuteScalar();
}
}
Investigate Command.ExecuteScalar:
using(var connection = new SqlConnection(myConnectionString))
{
connection.Open();
using(var command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = mySql;
var result = (int)command.ExecuteScalar();
}
}
If you're feeling really lazy, encapsulate it all in an extension method, like we do.
EDIT: As requested, an extension method:
public static T ExecuteScalar<T> (this SqlConnection connection, string sql)
{
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (string.IsNullOrEmpty(sql))
{
throw new ArgumentNullException("sql");
}
using(var command = connection.CreateCommand())
{
command.CommandText = sql;
command.CommandType = CommandType.Text;
return (T)command.ExecuteScalar();
}
}
Note, this version assumes you've properly built the SQL beforehand. I'd probably create a separate overload of this extension method that took two parameters: the stored procedure name and a List. That way, you could protect yourself against unwanted SQL injection attacks.