creating sql connection object once and using it several times - asp.net

i'm creating login and register page in MVC asp.net but problem is that for each purpose i have to do all SQl connection, command, try open etc which really makes it slow so i as wondering that if i can get rid of creating ti again and again and just create sqlconnection thing once and calling it again and again for login, registration etc
namespace LoginSys.Models
{
public class database
{
public ConnectionStatus connectDB(String name, String email, String pwd, String conStr)
{
// var con = conStr;
SqlConnection sqlCon = new SqlConnection(conStr);
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "insert into tblRegister (userName, userEmail, userPwd) values (#name, #email, #pwd)";
sqlCom.Parameters.AddWithValue("#name", name);
sqlCom.Parameters.AddWithValue("#email", email);
sqlCom.Parameters.AddWithValue("#pwd", pwd);
ConnectionStatus connectStatus = new ConnectionStatus();
int row_aff;
try
{
sqlCon.Open();
row_aff = sqlCom.ExecuteNonQuery();
connectStatus.Message = "OK";
}
catch(Exception ex)
{
connectStatus.Message = ex.Message;
}
finally
{
sqlCon.Close();
}
return connectStatus;
}
}
}

Actually you are not creating a new physical connection to the database. ADO.NET uses a connection pool. This means that even if you create a new instance of SqlConnection, you are not actually creating a new physical connection but are drawing one from the pool. Also when you call the .Close() method you are not actually closing the underlying connection. You are just returning it to the connection pool so that it can be reused.
So your code won't be slow because of that.
The only improvement I may recommend you to this code is to wrap the IDisposable objects in using statements:
public ConnectionStatus ConnectDB(string name, string email, string pwd, string conStr)
{
using (SqlConnection sqlCon = new SqlConnection(conStr))
using (SqlCommand sqlCom = sqlCon.CreateCommand())
{
sqlCon.Open();
sqlCom.CommandText = "insert into tblRegister (userName, userEmail, userPwd) values (#name, #email, #pwd)";
sqlCom.Parameters.AddWithValue("#name", name);
sqlCom.Parameters.AddWithValue("#email", email);
sqlCom.Parameters.AddWithValue("#pwd", pwd);
ConnectionStatus connectStatus = new ConnectionStatus();
try
{
sqlCom.ExecuteNonQuery();
connectStatus.Message = "OK";
}
catch(Exception ex)
{
connectStatus.Message = ex.Message;
}
return connectStatus;
}
}

Related

ASP.Net db connection issue

I'm new to ASP.Net & SQL Server and have the following code:
protected void btnShowData_Click(object sender, EventArgs e)
{
string connectionString;
SqlConnection cnn;
connectionString = #"Data Source=DESKTOP-RV7DDL4;Initial Catalog=Demodb
;User ID=DESKTOP-RV7DDL4\dbname;Password=test123";
cnn = new SqlConnection(connectionString);
SqlCommand command;
SqlDataReader dataReader;
String sql, Output = "";
sql = "Select TutorialID, TutorialName from demotb";
command = new SqlCommand(sql, cnn);
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
Output = Output + dataReader.GetValue(0) + " - " + dataReader.GetValue(1) + "</br>";
}
Response.Write(Output);
dataReader.Close();
command.Dispose();
cnn.Close();
lblName.Visible = false;
txtName.Visible = false;
lstLocation.Visible = false;
chkC.Visible = false;
chkASP.Visible = false;
rdMale.Visible = false;
rdFemale.Visible = false;
btnSubmit.Visible = false;
}
When I run the project I receive the following error:
An exception of type 'System.InvalidOperationException' occurred in System.Data.dll but was not handled in user code
Additional information: ExecuteReader requires an open and available Connection. The connection's current state is closed.
I thought the connection was made so not sure why it says the db is closed?
Try to to explicitly open the connection via the Open method on the SQL connection class.
Perhaps a using statement is more appropriate here. Like so:
using (var cnn = new SqlConnection(connectionString))
{
// Use the connection
}
Thanks for your help. I re-jigged things around and added the .Open method and it works!
string connectionString = null;
SqlConnection cnn;
SqlCommand command;
string sql, Output = "";
connectionString = #"Data Source=DESKTOP-RV7DDL4\SQLEXPRESS;Initial Catalog=DemoDBase
;User ID=sa;Password=test1234";
cnn = new SqlConnection(connectionString);
sql = "Select TutorialID, TutorialName from demoTable";
cnn.Open();
command = new SqlCommand(sql, cnn);
SqlDataReader dataReader;
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
Output = Output + dataReader.GetValue(0) + " - " + dataReader.GetValue(1) + "</br>";
}
Response.Write(Output);
dataReader.Close();
command.Dispose();
cnn.Close();

Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack when I use scope identity

Here is ehat I try to do
on button_click I read the values from the text boxes and insert them in them in the database.
as tourist number for example maybe two or three tourists with ExecuteScalar; i get the ids of teh tourists which are inserted!
public void cmdInsert_OnClick(object sender, EventArgs e)
{
if (Page.IsValid)
{
string numtourist = (string)Session["tourist_number"];
for (int i = 0; i < Int32.Parse(numtourist); i++)
{
TextBox tx888 = (TextBox)FindControl("txtNameK" + i.ToString());
TextBox tx888_1 = (TextBox)FindControl("txtMidNameK" + i.ToString());
TextBox tx888_2 = (TextBox)FindControl("txtLastNameK" + i.ToString());
string insertSQL = "INSERT INTO Tourist (Excursion_ID, Excursion_date_ID, Name_kir,Midname_kir, Lastname_kir)";
insertSQL += " VALUES (#Excursion_ID, #Excursion_date_ID, #Name_kir,#Midname_kir, #Lastname_kir) SELECT ##IDENTITY";
string connectionString = "Data Source = localhost\\SQLExpress;Initial Catalog=excursion;Integrated Security=SSPI";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
cmd.Parameters.AddWithValue("#Excursion_ID", Convert.ToInt32(mynew2));
cmd.Parameters.AddWithValue("#Excursion_date_ID", Convert.ToInt32(mynewnewstring));
cmd.Parameters.AddWithValue("#Name_kir", tx888.Text);
cmd.Parameters.AddWithValue("#MidName_kir", tx888_1.Text);
cmd.Parameters.AddWithValue("#LastName_kir", tx888_2.Text);
int added;
try
{
con.Open();
added = (int)cmd.ExecuteScalar();
lblproba.Text = "";
Tourist.Add(added);
lblproba.Text += Tourist.Count();
}
catch (Exception ex)
{
lblproba.Text += ex.Message;
}
finally
{
con.Close();
}
}
createReservation();
}
}
I call CreateReservationFunction AND i CREATE A NEW RESERVAION WITH THE ID OF THE USER WHO HAS MADE THE RESERVATION. wITH SELECT IDENTITY I TRY TO GET THE RESERVATION_ID of the reservation and here I get the exception "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack". So I wonder can this exception has something commn with the fact that in my solution exceptthe asp.net web projectI got library class in which I has .edmx file The entity framework model of my database and in my last form I don't use Ado,net but Entity framework
public void createReservation()
{
string insertSQL = "Insert INTO RESERVATIONS (User_ID) values (#User_ID) SELECT ##IDENTITY";
string connectionString = "Data Source = localhost\\SQLExpress;Initial Catalog=excursion;Integrated Security=SSPI";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
cmd.Parameters.AddWithValue("#User_ID", 9);
try
{
con.Open();
string added = cmd.ExecuteScalar().ToString();
createTouristReservation(added);
}
catch (Exception ex)
{
lblproba.Text+= ex.Message;
}
}
Don't use ##IDENTITY but SCOPE_IDENTITY and add a semicolon between the insert and the select.
string insertSQL = #"INSERT INTO Tourist (Excursion_ID, Excursion_date_ID, Name_kir,Midname_kir, Lastname_kir)
VALUES (#Excursion_ID, #Excursion_date_ID, #Name_kir,#Midname_kir, #Lastname_kir)
;SELECT CAST(scope_identity() AS int)";

Unable to connect to .MDB database with ASP.NET C#

I'm trying to create a simple user registration system using ASP.NET C# and an MS Access .mdb database. The problem is, whenever I attempt to register, the code fails at the OleDbCommand in the "try" and gets "caught" instead. I have used breakpoints in MS Visual Studio 2012 and all keys are present as far as I can tell. My code follows:
Here is my class where the registration method is located:
public static class DbUtil
{
private static OleDbConnection openConnection()
{
OleDbConnection con = new OleDbConnection();
try
{
string conString = #"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|MainDatabase.mdb";
con = new OleDbConnection(conString);
con.Open();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return con;
}
private static void closeConnection(OleDbConnection con)
{
try
{
con.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public static bool registerUser(string email, string password)
{
try
{
using (OleDbConnection con = openConnection())
{
string sqlString = #"INSERT INTO Users (Email, Password) VALUES (?, ?)";
using (OleDbCommand command = new OleDbCommand(sqlString, con))
{
command.Parameters.AddWithValue("Email", email);
command.Parameters.AddWithValue("Password", password);
command.ExecuteNonQuery();
closeConnection(con);
return true;
}
}
}
catch
{
return false;
}
}
}
Here is where the method is called:
public void btnRegisterSubmit_Click(object sender, EventArgs e)
{
string strEmail = txtRegisterEmail.Text;
string strPassword = txtRegisterPassword.Text;
bool regSuccess = DbUtil.registerUser(strEmail, strPassword);
if (regSuccess == false)
{
Response.Redirect("Default.aspx?reg=fail");
}
else
{
if (regSuccess == true)
{
Response.Redirect("Default.aspx?reg=success");
}
else
{
Response.Redirect("Default.aspx?reg=error");
}
}
}
I'm currently using the praised parameter method, for the first time. I did use a simple concatenation method in the SQL string, but this yielded the same problem.
Also, there are no errors printed or exceptions thrown.
Any help at all would be highly appreciated. Thanks in advance!
UPDATE:
Exception:
System.Data.OleDb.OleDbException (0x80040E14): Syntax error in INSERT INTO statement. at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr) at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult) at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method) at System.Data.OleDb.OleDbCommand.ExecuteNonQuery() at DbUtil.registerUser(String email, String password) in c:\Users\******\Documents\Visual Studio 2012\WebSites\********************\App_Code\DbUtil.cs:line 51
I'm not using any reserved words
password is indeed a reserved word in Access SQL. The following code fails with
OleDbException was unhandled: Syntax error in INSERT INTO statement.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
namespace oledbTest1
{
class Program
{
static void Main(string[] args)
{
using (var conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\__tmp\testData.accdb;"))
{
conn.Open();
using (var cmd = new OleDbCommand(
#"INSERT INTO Users (Email, Password) VALUES (?, ?)",
conn))
{
cmd.Parameters.AddWithValue("?", "gord#example.com");
cmd.Parameters.AddWithValue("?", "myPassword");
cmd.ExecuteNonQuery();
}
conn.Close();
}
Console.WriteLine("Done.");
Console.ReadKey();
}
}
}
If I change the code to...
...
using (var cmd = new OleDbCommand(
#"INSERT INTO Users (Email, [Password]) VALUES (?, ?)",
conn))
{
...
...then it works fine.
Managed to get this fixed. I rewrote the registerUser() method, and removed the using blocks and it now works great. Here's the code with the removed parts commented:
public static bool registerUser(string email, string password)
{
try
{
//using (OleDbConnection con = openConnection())
//{
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.Jet.OleDb.4.0;Data Source=|DataDirectory|MainDatabase.mdb");
string sqlString = "INSERT INTO [Users] ([Email], [Password]) VALUES (#Email, #Password)";
//using (OleDbCommand command = new OleDbCommand(sqlString, con))
//{
OleDbCommand command = new OleDbCommand(sqlString, con);
command.Parameters.AddWithValue("#Email", email);
command.Parameters.AddWithValue("#Password", password);
con.Open();
command.ExecuteNonQuery();
con.Close();
return true;
//}
//}
}
catch (Exception e)
{
return false;
//System.Diagnostics.Debug.WriteLine(e.Message);
}
}
Thanks for the comments :)

SqDataReader closed issue in .net

i have created a function which executes query and returns SqlDataReader, now i am using that in another function work with the returned data, but i gets the error saying reader is already closed. here is the functions:
public static SqlDataReader ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
SqlDataReader reader = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
reader = command.ExecuteReader();
}
}
return reader;
}
here is the code where i am calling the SqlDataReader
using (SqlDataReader reader = SqlHelper.ExecuteReader("select top 10 username from users", null, System.Data.CommandType.Text))
{
Response.Write(reader.IsClosed); //This returns True
}
EDIT
ExecuteReader with CommanBehavior ( automatically close connection after reading data)
To over come connection closing proble just make use of CommandBheviour
- CommandBehavior.CloseConnection
When you pass above values as argument to ExecuteReader
1. there is no need to close connection explicitly connection get close when you close your reader.
code will be like this no need to close connection explicitly
public void CreateMySqlDataReader(string mySelectQuery,string myConnectionString)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(mySelectQuery, myConnection);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
while(myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
myReader.Close();
//Implicitly closes the connection because CommandBehavior.CloseConnection was specified.
}
its causing problem because you are closing connection
SqlReader always make use of open connection i.e live connection which is open when you use this
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
it dispose connection object which is used by reader object that why its returing IsColosed as true
If you wanto return value the objec than make use of DataTable which is disconnected data object and doens makse use of connection
Modified code
public static DataTable ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
DataTable dt = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
}
}
return dt;
}
DataReader needs an Open Connection. What you can do it either return a DataTable or Have custom class to represent the results of your SQL query and return an instance of that.
Create a Class to represent your Entity
public class Customer
{
public int ID { set;get;}
public string Name { set;get;}
}
And inside your method;
public List<Customer> GetCustomer()
{
List<Customer> custList=new List<Customer>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("yourParameterizedSQLQuery",
connection))
{
//Add parameters if needed
connection.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
cust=new Customer();
while(reader.Read())
{
var cust=new Customer();
// TO DO :Do db null checking before reading
cust.ID=reader.GetInt32(reader.GetOrdinal("ID"));
cust.Name=reader.GetString(reader.GetOrdinal("Name"));
custList.Add(cust);
}
}
}
}
}
return custList;
}
The problem is that you have using SqlConnection which closes the connection to your database when leaving the scope.
SqlDataReader needs a "still open" connection. Returning it to the parent does not keep the connection open.
Your choice are basically to return a DataSet, which is an "unconnected" data source or change the way you manage your connection to open it, use the SqlDataReader, close the connection.
You may have to leave the connection open and let the calling code close the connection associated with the reader.
I had this challenge so I change my return type to DataTable
reader = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;
That way I don't have to worry about closing the connection outside that method

ASP.NET using md5 to authenticate users

Currently i am doing a little project, the user registration password field is encrypted in the database, therefore I need to authenticate users using md5 algorithm also but my code is not working, whenever i try to input the correct password(unencrypted) it enters but later out i figured out that any password I type, the system will accept it even it doesn't matches in the database.
Can you help me? Here is my code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string pAssword = txtPassword.Text;
MD5CryptoServiceProvider encryptor = new MD5CryptoServiceProvider();
byte[] encryptedValue;
UTF8Encoding encoder = new UTF8Encoding();
encryptedValue = encryptor.ComputeHash(encoder.GetBytes(pAssword));
DataSet ds = new DataSet();
ds = (startWebService.getAllUsers());
if (ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dRow in ds.Tables[0].Rows)
{
string userName = dRow["UserName"].ToString();
string passWord = dRow["Password"].ToString();
string acctNo = dRow["AccountNumber"].ToString();
if (userName == txtUsername.Text.ToString() && acctNo == txtAcctNo.Text.ToString() && passWord == encryptedValue.ToString() )
{
FormsAuthentication.RedirectFromLoginPage(txtUsername.Text.ToString(), false);
lblError.Text = "You got it!";
Response.Redirect("MyAccount.aspx");
}
else
{
this.lblError.ForeColor = System.Drawing.Color.Red;
this.lblError.Text = "Either you have been type an incorrect network credentials or you have reached the maximum login attempts for your account.Please try again or contact the system administrator.";
startWebService.updateFailedLogin(txtAcctNo.Text.ToString(), txtUsername.Text.ToString());
}
}
}
}
my web services:
private DataSet GetDataSet(string strSPROC)
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = strSPROC;
conn.Open();
SqlDataAdapter myDataAdapter = new SqlDataAdapter();
myDataAdapter.SelectCommand = cmd;
DataSet dsMT = new DataSet();
myDataAdapter.Fill(dsMT);
return dsMT;
conn.Close();
}
[WebMethod]
public DataSet getAllUsers()
{
return GetDataSet("ELMS_ALLINTERNETUSERS");
}
Please help me, I have to correct this in a way that the system will accepts the correct equivalent of encrypted text for example I type: spain = wdhs3x9029 but i tried to type philippines , it accepts also.
There is a nice built-in method for hashing passwords (you can use MD5 with it):
string encryptedValue = FormsAuthentication.HashPasswordForStoringInConfigFile(pAssword, "MD5");
You can read more about this method here. If you need to reinvent the wheel, then I suggest you change your method of getting hash as string to something more like this:
MD5CryptoServiceProvider encryptor = new MD5CryptoServiceProvider();
UTF8Encoding encoder = new UTF8Encoding();
byte[] encryptedValueBytes = encryptor.ComputeHash(encoder.GetBytes(pAssword));
StringBuilder encryptedValueBuilder = new StringBuilder();
for (int i = 0; i < encryptedValueBytes.Length; i++)
{
encryptedValueBuilder.Append(data[i].ToString("x2"));
}
string encryptedValue = encryptedValueBuilder.ToString();
instead of simple .ToString() on byte array.

Resources