This is my connection class
class connection
{
public SqlConnection con;
public SqlCommand cmd;
public SqlDataAdapter sda;
String pkk;
public void connectionFunc()
{
con = new SqlConnection(#"Data Source=.;Initial Catalog=payroll;Integrated Security=True");
con.Open();
}
public void dataSend(String SQL)
{
try
{
connectionFunc();
cmd = new SqlCommand(SQL, con);
cmd.ExecuteNonQuery();
pkk = "";
}
catch(Exception)
{
pkk = "error";
}
con.Close();
}
public void dataGet(String SQL)
{
try
{
connectionFunc();
sda = new SqlDataAdapter(SQL, con);
}
catch(Exception)
{
}
}
}
And this is the use of the class:
connection con = new connection();
con.dataGet("Select * from [users] Where Userame = '" + textBox1.Text + "' and Password = '" + textBox2.Text + "'");
DataTable dt = new DataTable();
// this line throws an error
con.sda.Fill(dt);
if(dt.Rows.Count > 0)
{
this.Hide();
Mainpage obj = new Mainpage();
obj.Show();
}
else
{
MessageBox.Show("Invalid UserName Or Password..!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
I get the following error:
An unhandled exception of type 'System.NullReferenceException' occurred in Payroll_Manegement.exe
I don't know what is the issue here if someone could help me that would be great.
To answer your question: the error comes from the fact that your DataTable only is instantiated but not populated before the SqlDataAdapter.Fill is fired, so when the latter tries to do something useful it can only return an exception explaining exactly what is wrong.
Your connection class pains my eyes in terms of insecure variable scope (why use public everywhere?) and non-existent connection pooling. Using a class like this opens up your application for all kinds of insecure horror. Please try to keep things simple if your application is not too complicated; the basics from the .NET Framework should already be enough for your purposes. Just do something similar to the code below (with regard to parameterization of your queries like the others suggested):
string connectionString = "server=myServer;User ID=myUser;Password=myPwd;"; // could also be internal static on class level
string theQuery = "SELECT * FROM dbo.Users WHERE Username = #userName AND Password = #password";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand(theQuery, sqlConnection))
{
sqlCommand.Parameters.AddWithValue("#userName", textBox1.Text);
sqlCommand.Parameters.AddWithValue("#password", textBox2.Text);
DataTable dataTable = new DataTable();
dataTable.Load(sqlCommand.ExecuteReader());
if (dataTable.Rows > 0)
{
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
sqlDataAdapter.Fill(dataTable);
}
}
}
Alternatively, for the more complex applications you could study the Entity Framework https://learn.microsoft.com/en-us/ef/ef6/get-started first and train yourself in not re-inventing wheels. It will take some time to adapt but will really pay off.
Good luck improving your code!
Related
I'm trying to delete record from data base MSSQL by entering the ID and hit delete btn. i didn't get any error and it give recorded deleted successful but once i check database i see the record doesn't deleted
protected void btnDelete_Click(object sender, EventArgs e)
{
try
{
if (txtImgID.Text == "")
{
Response.Write("Enter Image Id To Delete");
}
else
{
SqlCommand cmd = new SqlCommand();
SqlConnection con = new SqlConnection();
con = new SqlConnection(ConfigurationManager.ConnectionStrings["GMSConnectionString"].ConnectionString);
con.Open();
cmd = new SqlCommand("delete from certf where id=" + txtImgID.Text + "", con);
lblsubmitt.Text = "Data Deleted Sucessfully";
}
}
catch (Exception)
{
lblsubmitt.Text = "You haven't Submited any data";
}
}
var idToDelete = int.Parse(txtImgID.Text); // this is not necessary if the data type in the DB is actually a string
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["GMSConnectionString"].ConnectionString))
using (SqlCommand cmd = new SqlCommand("DELETE FROM [certf] WHERE id = #id", con))
{
// I am assuming that id is an integer but if it is a varchar/string then use the line below this one
// cmd.Parameters.Add("#id", SqlDbType.VarChar, 100).Value = txtImgID.Text;
cmd.Parameters.Add("#id", SqlDbType.Int32).Value = idToDelete;
cmd.ExecuteNonQuery();
}
You need to call ExecuteNonQuery which executes the query against the database.
Always use parameters instead of string concatenation in your queries. It guards against sql injection and ensures you never has issues with strings that contain escape characters.
I did not include any error handling or return messages but do note that you are throwing away all the good stuff in your excetion handler's catch block, you will never know why a query failed after this has executed.
I created the following code:
public static bool setHeadword(int id, string headword)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\pms.mdf;Integrated Security=True";
conn.Open();
SqlCommand command = new SqlCommand("UPDATE headwords SET Headword = #headword WHERE Id = #id", conn);
command.Parameters.AddWithValue("#headword", headword);
command.Parameters.AddWithValue("#id", id);
int result = command.ExecuteNonQuery();
conn.Close();
return true;
}
But the code doesn't work because the value in the database doesn't change.
If I run the code manually in the database the change takes place. But it won't work with C#.
Also the result variable are holding the right number of affected rows (1 in this case).
I'm not sure I have to flush the changes or something else.
Thanks for your help and best regards
Franz
static void Update(int id, string headword)
{
try
{
//You should create connectionString with correct details otherwise fail connection
string connectionString =
"server=.;" +
"initial catalog=employee;" +
"user id=sa;" +
"password=123";
using (SqlConnection conn =
new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd =
new SqlCommand("UPDATE headwords SET Headword=#headword" +
" WHERE Id=#Id", conn))
{
cmd.Parameters.AddWithValue("#Id", id);
cmd.Parameters.AddWithValue("#headword", headword);
int rows = cmd.ExecuteNonQuery();
}
}
}
catch (SqlException ex)
{
//Handle sql Exception
}
}
In the project I call a method to query additional information with a SqlConnection block, but then I validate if exists in a second table using another sqlconnection block, but it is supposed to be disposed (closed) after getting back to the method InsertNewData, but when calling to Open the connection for the Insert, I'm getting the following message:
The connection was not closed. The connection's current state is open.
My code is like this:
public void InsertNewData(string operation)
{
DataTable dt = new DataTable();
try
{
if (operation!= string.Empty)
{
using (SqlConnection oconn = new SqlConnection(myDBone))
{
SqlCommand cmd = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();
string query = "SELECT * FROM operations "+
"WHERE idoper=#id";
oconn.Open();
cmd = new SqlCommand(query, oconn);
cmd.Parameters.Add(new SqlParameter("#id", operation.ToString()));
da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
if (dt.Rows.Count > 0)
{
using (SqlConnection con = new SqlConnection(myDBtwo))
{
SqlCommand com = new SqlCommand();
string query= "";
foreach (DataRow x in dt.Rows)
{
if (ValidateData(x) == false)
{
query= "INSERT INTO history(iddata,description, datehist ) "+
" VALUES(#id,#descrip,GETDATE())";
con.Open(); //Here throws the Exception error
com = new SqlCommand(query, con);
com.Parameters.Add(new SqlParameter("#id", x["idoper"].ToString()));
com.Parameters.Add(new SqlParameter("#descrip", x["description"] ));
com.ExecuteNonQuery();
}
}
}
}
}
}
catch (Exception x)
{
throw x;
}
}
public bool ValidateData(DataRow row)
{
bool exists= false;
string operation= row["idoper"].ToString();
string descrip= row["description"].ToString();
if (operation!= string.Empty && descrip!= string.Empty)
{
using (SqlConnection oconn = new SqlConnection(sqlrastreo))
{
SqlCommand cmd = new SqlCommand();
string query = "SELECT COUNT(*) FROM history "+
"WHERE iddata=#id AND description=#descrip";
oconn.Open();
cmd = new SqlCommand(query, oconn);
com.Parameters.Add(new SqlParameter("#id", operation));
com.Parameters.Add(new SqlParameter("#descrip", descrip));
int count = (int) cmd.ExecuteScalar();
if (count > 0)
exists= true;
}// Here it should be Disposed or closed the SqlConnection
}
return exists;
}
What I'm doing wrong, because it's suppose to be closed the other connection and the other hasn't been opened ? or Should I Still call the Close() method for each SqlConnection inside the block Using?
Updated:
I've changed to parameters for best reading code and recommendation syntax.
NOTE
The values and parameters aren't the real ones, my real table descriptions have about 8 fields, but I validate with just two parameters that aren't primary key, but considering that I can't edit the table properties (Have only reading permissions for that database).
Update 2:
Thanks to the recommendation of Sean Lange, it was better and so simple to use a Store Procedure (SP) to validate and insert at the same time, so I do it as follow in code of the process:
public void InsertNewData(string operation)
{
try
{
if(operation == string.Empty)
return;
using(SqlConnection con = new SqlConnection(myDBtwo))
{
con.Open();
var cmd = new SqlCommand("SP_InsertData", con);
cmd.Parameters.Add(new SqlParameter("#id", operation));
cmd.ExecuteNonQuery();
}
}
catch(Exception ex)
{ throw ex; }
}
And then in my SP I insert a select statement of the parameter, to avoid duplicates and also do it in One go:
CREATE PROCEDURE SP_InsertData #id VARCHAR(10)
AS
BEGIN
INSERT INTO History
SELECT O.idoper, O.description
FROM myDBone.dbo.operations O
LEFT JOIN History H
ON H.iddata = O.idoper AND H.description = O.description
WHERE O.idoper=#id AND H.iddata IS NULL
END
Thanks for your support, and hope it helps someone.
First your code is badly written,as they have suggested you don't need to validate,try catch will do it for you.second opening a connection inside a loop ( foreach in your case) will will result to trying to open already open connection. Example here you could do something like
query= "INSERT INTO history(iddata,description, datehist" VALUES(#id,#descrip,GETDATE())";
using (SqlConnection con = new SqlConnection(myDBtwo))
{
con.Open();
SqlCommand com = new SqlCommand(query,con);
foreach (DataRow x in dt.Rows)
{
com.Parameters.Add(new SqlParameter("#id", x["idoper"].ToString()));
com.Parameters.Add(new SqlParameter("#descrip", x["description"] ));
com.ExecuteNonQuery();
}
}
}
I have a class which I have written all my methods there.
then I have my firstpage of web application which I have some codes there.
I face this
$exception {"Fill: SelectCommand.Connection property has not been initialized."} System.Exception {System.InvalidOperationException}
in the line :
sda.Fill(dsUsers.tblMembers);
here is my code so I hope u can help me:
namespace MosquesNetwork
{
public class cUsers2
{
SqlConnection scn;
SqlDataAdapter sda;
SqlCommandBuilder scb;
SqlCommand SqlStr;
public cUsers2()
{
SqlConnection scn = new SqlConnection (ConfigurationManager.ConnectionStrings["MosquesDBConnectionString"].ConnectionString);
sda = new SqlDataAdapter();
scb = new SqlCommandBuilder(sda);
}
public bool CheckUserName(string UserName)
{
DsUsers2 dsUsers=new DsUsers2();
bool Success;
string SqlStr="select * from tblUsers where Username='"+UserName+"' ";
sda.SelectCommand=new SqlCommand(SqlStr, scn);
sda.Fill(dsUsers.tblMembers);
sda.Fill(dsUsers.tblMembers);
Success=dsUsers.tblMembers.Rows.Count>0;
return Success;
}
then I have this code while the login button is pressed in webform:
protected void Button1_Click(object sender, EventArgs e)
{
if (txtuser.Text.Trim().Length>0 && txtpass.Value.Length>0 )
{
cUsers2 cUsers=new cUsers2();
DsUsers2 dsUser=new DsUsers2();
bool Success;
if (txtuser.Text.Trim()=="admin")
{
Success=cUsers.CheckAdminPass(txtuser.Text.Trim(),txtpass.Value.Trim());
if (Success)
{
Response.Redirect("WebForm2.aspx");
}
}
dsUser=cUsers.Checkpassword(txtuser.Text.Trim(), txtpass.Value.Trim(),out Success);
if(Success)
{
Session["ID"]=dsUser.tblMembers.Rows[0][dsUser.tblMembers.IDUserColumn].ToString();
System.Web.HttpContext.Current.Response.Redirect("frmProfile.aspx");
}
else lblerror.Text="invalid username & password";
}
}
Look at your constructor:
SqlConnection scn = new SqlConnection(...);
That's declaring a separate scn local variable, so the scn instance variable is staying as null. If you just change it to:
scn = new SqlConnection(...);
that may well fix the immediate problem. It's not a nice design in my view - I'd prefer to create the SqlConnection in a using block where you actually need it - but that's what's going wrong for now...
I got also this problem. after search the problem found that the object of connection that i have provide SqlDataAdapter is not Initialize so the connection passed as null
Vishal Sir, If You are Getting that Problem then Be sure whether you are passing the 'cmd' to the SQL DATA ADAPTER.
for eg:
ad = new SqlDataAdapter(cmd);
//Try To Fetch The Value Like this...
protected void Search_Emp_Click(object sender, EventArgs e)
{
SqlCommand cmd;
SqlConnection con;
SqlDataAdapter ad;
con = new SqlConnection(); //making instance of SqlConnection
con.ConnectionString = ConfigurationManager.ConnectionStrings["cn"].ConnectionString; //Invoking Connection String
con.Open(); //Opening Connection
if (Ddl_Emp_Search.SelectedItem.Text == "Date Of Joining")
{
cmd = new SqlCommand("Select Emp_Name,Contact_No,City,Emp_Desig,Place_Code from emp_registration where Emp_Doj=#Emp_Doj",con);
cmd.Parameters.Add("#Emp_Doj", SqlDbType.NVarChar, 50).Value = TextBox1.Text;
}
else if (Ddl_Emp_Search.SelectedItem.Text == "Name")
{
cmd = new SqlCommand("Select Emp_Name,Place_Code,Emp_Code,Emp_Desig from emp_registration where Emp_Name=#Emp_Name", con);
cmd.Parameters.Add("#Emp_Name", SqlDbType.NVarChar, 50).Value = TextBox1.Text;
}
else if (Ddl_Emp_Search.SelectedItem.Text == "Employee Code")
{
cmd = new SqlCommand("Select Emp_Name,Contact_No,City,Emp_Desig,Place_Code from emp_registration where Emp_Code=#Emp_Code", con);
cmd.Parameters.Add("#Emp_Code", SqlDbType.NVarChar, 50).Value = TextBox1.Text;
}
else if (Ddl_Emp_Search.SelectedItem.Text == "City")
{
cmd = new SqlCommand("Select Emp_Name,Contact_No,City,Emp_Desig,Place_Code from emp_registration where City=#City", con);
cmd.Parameters.Add("#City", SqlDbType.NVarChar, 50).Value = TextBox1.Text;
}
else
{
Response.Write("There is Something Worng....");
}
ad = new SqlDataAdapter(cmd); // Here IS THE PROBLEM WHEN YOU DOES'NT PASS CMD (Command instance) to the Data Adapter then there is a problem of ( Fill: SelectCommand.Connection property has not been initialized)
DataSet ds = new DataSet();
ad.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
}
public class SqlHelper
{
public SqlHelper()
{
}
public static SqlConnection GetConnection()
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=" + System.Web.HttpContext.Current.Server.MapPath(#"~\App_Data\learn.mdf") + ";Integrated Security=True;User Instance=True";
return conn;
}
public static SqlDataReader ExecuteReader(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader dr = null;
try
{
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
catch
{
con.Close();
return null;
}
return dr;
}
public static Object ExecuteScalar(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
Object val = null;
try
{
val = cmd.ExecuteScalar();
}
catch
{
con.Close();
return null;
}
finally
{
con.Close();
}
return val;
}
public static DataSet ExecuteDataSet(string sql)
{
SqlConnection con = GetConnection();
SqlCommand cmd = new SqlCommand(sql, con);
DataSet ds = new DataSet();
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
try
{
adapt.Fill(ds);
}
catch
{
con.Close();
}
return ds;
}
public static void ExecuteNonQuery(string sql)
{
SqlConnection con = GetConnection();
con.Open();
SqlCommand cmd = new SqlCommand(sql, con);
try
{
cmd.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
This is the Class which I use to implement every access to my database . But I think that the way I do connection with the database is a little bit overblown cause I have to hit the Connect function every time I need something . As well as other users going to do the same which kills the performance.
So what is the perfect way to connect with the database - and to stay connected if that better . Note that I use the database in many pages!
Thanks
First, you should be using "using" statements to ensure that all your ADO.NET objects are properly disposed of in the event of a failure:
public static void ExecuteNonQuery(string sql)
{
using(var con = GetConnection())
{
con.Open();
using(var cmd = new SqlCommand(sql, con))
{
cmd.ExecuteNonQuery();
}
}
}
However, having said that, I don't really see a problem with this approach. The advantage is that the connections, commands, adapters and whatnot are properly disposed of every time you execute a bit of SQL. If you were to make a single static SqlConnection instance, you'd escalate the chances that the connection is already in use (when, for example, iterating over the contents of a SqlDataReader).
If you are really concerned about it, provide overloads that take a connection as an extra parameter:
public static void ExecuteNonQuery(string sql, SqlConnection connection)
{
using(var cmd = new SqlCommand(sql, con))
{
cmd.ExecuteNonQuery();
}
}
This way, callers can either execute a bit of SQL that doesn't require multiple calls, or they can call your GetConnectionMethod to obtain a connection, and pass it to multiple calls.
If this is used for a web site then you have to consider that between requests for pages, even from the same browser, your server state will be torn down (in general terms) so there's nothing really to be gained from trying to maintain your SQL connection between pages. That's the first thing.
If each page is the result of a single database connection then you are probably as optimised as you really need to be, if you are making several connections over the generation of a page then you may want to look at keeping a connection alive until you have finished retrieving data; either by maintaining the connection or optimising your data retrieval to limit the back and forth between your app and the db.
Maintaining a database connection is the job of the connection pool, and not the connection consumer. The best practice is to aquire a connection as late as possible and release it as soon as possible.
using(var connection = new SqlConnection(YourConnectionStringHelperFunction())
{
}
One thing that YOu might take into consideration is the Dependency Injection PAttern and some IoC controller. If every page needs to have this connection make this an injectable property (constructor probably wont work unless You implement some kind of infrastructure classes like Request) use some container (Unity, Castle, StructureMap) pack the needed things up (maybe cache, maybe some other things) and let the container do the magic (by magic I mean tons of boilerplate code) for You.
luke
First you can write a seperate class like this :
Get method for getting data (with a Select query) and Set method for manipulating data (Insert, Update, Delete)
using System.Data;
using System.Data.Odbc;
using System.Data.SqlClient; //using this you can replace instead odbc to sql
// Example SqlCommand, SqlDataAdapter
class DataBaseConnection
{
private OdbcConnection conn1 = new OdbcConnection(#"FILEDSN=C:/OTPub/Ot.dsn;" + "Uid=sa;" + "Pwd=otdata#123;"); //"DSN=Ot_DataODBC;" + "Uid=sa;" + "Pwd=otdata#123;"
//insert,update,delete
public int SetData(string query)
{
try
{
conn1.Open();
OdbcCommand command = new OdbcCommand(query, conn1);
int rs = command.ExecuteNonQuery();
conn1.Close();
return rs;
}
catch (Exception ex)
{
conn1.Close();
throw ex;
}
}
//select
public System.Data.DataTable GetData(string sql)
{
try
{
conn1.Open();
OdbcDataAdapter adpt = new OdbcDataAdapter(sql, conn1);
DataTable dt = new DataTable();
adpt.Fill(dt);
conn1.Close();
return dt;
}
catch (Exception ex)
{
conn1.Close();
throw ex;
}
}
}
in your form you can make object to that database connection class
DataBaseConnection db = new DataBaseConnection();
now you cal call get set with your get set method as following
string sqlSpecialHoliyday = "SELECT * FROM Holiday WHERE Date_Time='" + selectdate + "' AND IDH='50'";
DataTable dtAdditionalholily = db.GetData(sqlSpecialHoliyday);
AD you can Set Data Using Set method
string insertloginlog = "INSERT INTO Login_Log (Service_No, Machine_Name) VALUES ('" + serviceID + "','" + machiname + "')";
int ret = db.SetData(insertloginlog);
Hope This will help!