I have the return ExecuteScalar inside using blocks. And when I run the method for the first time it takes some time(I am using localhost). When I run same method for the second time it is very quick, like the connection was open. WHy is it so quick the second time?
(...)
using (var sqlConnection = new SqlConnection(connString))
{
using (var sqlCmd = new SqlCommand(cmdText, sqlConnection))
{
sqlCmd.Parameters.Add("#database", System.Data.SqlDbType.NVarChar).Value = "dbName";
sqlConnection.Open();
return Convert.ToInt32(sqlCmd.ExecuteScalar()) == 1;
}
;
}
or here:
using (var sqlConnection = new SqlConnection(connString))
{
using (var sqlCmd = new SqlCommand(cmdText, sqlConnection))
{
sqlCmd.Parameters.Add("#Param1", System.Data.SqlDbType.NVarChar).Value = "ParamValue";
sqlConnection.Open();
sqlCmd.ExecuteScalar();
if ((int)sqlCmd.ExecuteScalar() != 1)
{
using (SqlCommand command = new SqlCommand("CREATE TABLE TableName (ID int IDENTITY(1,1) PRIMARY KEY, (structure code here...)", sqlConnection))
{
command.ExecuteNonQuery();
}
}
}
}
In any case, the second time I run the method that has these I get almost instant response.
Related
The first SQL is executing but the second one doesn't seem to work.
When i change the query to the first one it works just fine but when I put it like that it doesn't seem to work for some reason.
I've just started learning MySQL i'm really struggling with this one and understanding the language.
//Classic One that checks if the hwid is there
public void checkHWID(string HWID)
{
string line;
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users WHERE HWID = #HWID", con))
{
cmd.Parameters.AddWithValue("#HWID", HWID);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
line = reader[1].ToString();
Console.Write(line);
con.Close();
}
else
{
updateHWID(HWID);
}
}
}
}
}
//This one doesn't seem to update the hwid but when i change the query to the first one it works just fine
public void updateHWID(String HWID)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO USERS(hwid) VALUES(#HWID)", connection))
{
command.Parameters.AddWithValue("#HWID", HWID);
connection.Close();
}
}
}
Your SQL statement in the updateHWID function isn't working primarily because it is missing the code that executes the command you created.
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO USERS(hwid) VALUES(#HWID)", connection))
{
command.Parameters.AddWithValue("#HWID", HWID);
command.ExecuteNonQuery(); // ADD THIS LINE
}
connection.Close();
Then assuming your table only requires the hwid and no other columns then this could work. If your table has other columns that don't allow nulls then you may get an error for the missing column values.
I am Creating WinForm application using C# and SqlServer. I have to handle many database CRUD Queries on it. And also there are so many forms and so many controllers.
Now I want to know is, If i create common class for handle database connectivity with many methods for open connection, close connection, execute Sql command or do any other data retrievals. This method is good or bad?
or below method for run every query is good or bad?
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=MYDB"))
{
connection.Open();
// Pool A is created.
}
which method is better for performance and security?
Here are some points to think about when using a connection.
1) Dispose the connection object as soon as you no longer need it by using the using statement:
using (var conn = new SqlConnection(connectionstring))
{
// your sql magic goes here
}
2) If you're not disposing the object immediately, you can make sure the connection is closed using a try-finally statement:
var conn = new SqlConnection(connectionstring);
try
{
// do sql shizzle
}
finally
{
conn.Close();
}
3) To prevent SQL injection, use parameterized queries, never concatenated strings
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using(var comm = new SqlCommand("select * from FooBar where foo = #foo", conn))
{
comm.Parameters.Add(new SqlParameter("#foo", "bar"));
// also possible:
// comm.Parameters.AddWithValue("#foo", "bar");
using(var reader = comm.ExecuteReader())
{
// Do stuff with the reader;
}
}
}
4) If you're performing multiple update, insert or delete statements, and they all need to be succesful at once, use a transaction:
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using(var trans = conn.BeginTransaction())
{
try
{
using(var comm = new SqlCommand("delete from FooBar where fooId = #foo", conn, trans))
{
comm.Parameters.Add(new SqlParameter { ParameterName = "#foo", DbType = System.Data.DbType.Int32 });
for(int i = 0; i < 10 ; i++)
{
comm.Parameters["#foo"].Value = i;
comm.ExecuteNonQuery();
}
}
trans.Commit();
}
catch (Exception exe)
{
trans.Rollback();
// do some logging
}
}
}
5) Stored procedures are used similarly:
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using (var comm = new SqlCommand("FooBarProcedure", conn) { CommandType = CommandType.StoredProcedure })
{
comm.Parameters.Add(new SqlParameter("#FooBar", "shizzle"));
comm.ExecuteNonQuery();
}
}
(Source stored procedures: this Answer)
Multi threading: The safest way to use multi threading and SQL connections is to always close and dispose your connection object. It's the behavior the SqlConnection was designed for. (Source: Answer John Skeet)
Best practice is make a common DBHelper class and create CRUD methods into that class.
I am adding code snippet.This may help you.
web.config
<connectionStrings>
<add name="mssqltips"
connectionString="data source=localhost;initial catalog=mssqltips;Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>
DBHelper.cs
//Opening Connection
public SqlConnection GetConnection(string connectionName)
{
string cnstr = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
SqlConnection cn = new SqlConnection(cnstr);
cn.Open();
return cn;
}
//for select
public DataSet ExecuteQuery(
string connectionName,
string storedProcName,
Dictionary<string, sqlparameter=""> procParameters
)
{
DataSet ds = new DataSet();
using(SqlConnection cn = GetConnection(connectionName))
{
using(SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProcName;
// assign parameters passed in to the command
foreach (var procParameter in procParameters)
{
cmd.Parameters.Add(procParameter.Value);
}
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(ds);
}
}
}
return ds;
}
//for insert,update,delete
public int ExecuteCommand(
string connectionName,
string storedProcName,
Dictionary<string, SqlParameter> procParameters
)
{
int rc;
using (SqlConnection cn = GetConnection(connectionName))
{
// create a SQL command to execute the stored procedure
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProcName;
// assign parameters passed in to the command
foreach (var procParameter in procParameters)
{
cmd.Parameters.Add(procParameter.Value);
}
rc = cmd.ExecuteNonQuery();
}
}
return rc;
}
If you do not want to dispose context every time you can create repository class and inject SqlConnection inside.
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=MYDB"))
{
repository.SetConnection(connection);
var values = repository.GetSomething();
}
And Create Class:
public Class Repository
{
private SqlConnection _connection {get; set;}
public void SetConnection(SetConnection connection)
{
_connection = connection;
}
public string GetSomething()
{
_connection.Open();
//do stuff with _connection
_connection.Close();
}
}
Anyway I recommend you to read about ORM's (Entity Framework or Dapper) and SQL injection attack.
I have two buttons on a page, one that logs a start time, and one that logs an end time.
The start time button performs an sql insert.
At that point i need to grab the primary key that's create. To do this i want to use the sql command (output inserted).
Then when the stop time is clicked,the row should be update with a stop time using the primary key from the start in the where clause.
I believe insert SQL is correct but i don't know how to pass the primary key to the next command.
Code dump, with what i have so far.
var command1 = "INSERT INTO [Time] ([Start Time], [Work Order]) OUTPUT INSERTED.PrimaryKey VALUES (#StartTime, #Work_Order)";
using (SqlConnection cnn1 = new SqlConnection(cnnString))
{
using (SqlCommand cmd1 = new SqlCommand(command1, cnn1))
{
cmd1.Parameters.AddWithValue("#StartTime", SqlDbType.DateTime).Value = System.DateTime.Now;
cmd1.Parameters.AddWithValue("#Work_Order", SqlDbType.Int).Value = e.CommandArgument;
cnn1.Open();
Label1.Text = cmd1.ExecuteScalar().ToString();
cnn1.Close();
}
}
var command = "UPDATE [Time] SET [Stop Time] = #StopTime WHERE [PrimaryKey] = #PrimaryKey";
using (SqlConnection cnn = new SqlConnection(cnnString))
{
using (SqlCommand cmd = new SqlCommand(command, cnn))
{
cmd.Parameters.AddWithValue("#StopTime", SqlDbType.DateTime).Value = System.DateTime.Now;
cmd.Parameters.AddWithValue("#PrimaryKey", *PrimaryKey from INSERT output*
cnn.Open();
cmd.ExecuteNonQuery();
}
}
instead of having it go to the label have it go to an int and then set the label text with the int. Then pass the int on the second part. Declare the int outside the scope of the using statements though or it will be disposed and you will get a null reference exception when you try and call it later.
Edit: To add, this would be better if you convert to stored procs and define the SqlParameter objects (you don't have them, you'll need them).
SqlParameter
int myPK;
var command1 = "INSERT INTO [Time] ([Start Time], [Work Order]) OUTPUT INSERTED.PrimaryKey VALUES (#StartTime, #Work_Order)";
using (SqlConnection cnn1 = new SqlConnection(cnnString))
{
using (SqlCommand cmd1 = new SqlCommand(command1, cnn1))
{
cmd1.Parameters.AddWithValue("#StartTime", SqlDbType.DateTime).Value = System.DateTime.Now;
cmd1.Parameters.AddWithValue("#Work_Order", SqlDbType.Int).Value = e.CommandArgument;
cnn1.Open();
myPk = Convert.ToInt32(cmd1.ExecuteScalar());
Label1.Text = myPk.ToString();
cnn1.Close();
}
}
var command = "UPDATE [Time] SET [Stop Time] = #StopTime WHERE [PrimaryKey] = #PrimaryKey";
using (SqlConnection cnn = new SqlConnection(cnnString))
{
using (SqlCommand cmd = new SqlCommand(command, cnn))
{
cmd.Parameters.AddWithValue("#StopTime", SqlDbType.DateTime).Value = System.DateTime.Now;
cmd.Parameters.AddWithValue("#PrimaryKey", myPK);
FindControl("Work_OrderLabel"); ;
cnn.Open();
cmd.ExecuteNonQuery();
}
}
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;
}
}
}
}
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;
}
}