update database based on gridview value - asp.net

I have a grid view which uses SQL to calculate information that I need! I want to put this calculated total into another table in database.
SELECT StaffDetails.StaffID, SUM(HolidayRequests.RequestTotalDays) AS Expr1
FROM HolidayRequests INNER JOIN StaffDetails ON HolidayRequests.Username = StaffDetails.UserName
WHERE (StaffDetails.StaffID = #staffID)
GROUP BY StaffDetails.StaffID, HolidayRequests.ApprovalStatus
HAVING (HolidayRequests.ApprovalStatus = N'approved')
It basically calculates the total number of approved holiday requests for a staff member which is correct. I want this number to then update the HolidayTaken field in another table each time a holiday is approved.
I have tried an update however you cannot use an aggregate in an update as I have found...Any idea how else I can do this..

you could load the executed Query into a "DataReader" or "DataSet" and from there load the information to the new Table.
you could do:
SqlConnection conn = "You connection";
SqlCommand cmd = new SqlCommand(conn);
cmd.CommandText = "YOUR QUERY";
SqlDataReader rdr = cmd.ExecuteReader();
String UpdateQuery;
while (rdr.Read())
{
UpdateQuery = "UPDATE table set col1=#Expr1 WHERE condition"
cmd.Parameters.AddWithValue("#Expr1", rdr["Expr1"].ToString());
//run update query
cmd.CommandText = UpdateQuery;
cmd.ExecuteNonQuery();
return;
}
cmd.Connection.Close();

Try this
UPDATE StaffDetails a
SET a.HolidayTaken = (SELECT SUM(HolidayRequests.RequestTotalDays)
FROM HolidayRequests INNER JOIN StaffDetails b ON HolidayRequests.Username = b.UserName
WHERE (b.StaffID = #staffID)
GROUP BY b.StaffID, HolidayRequests.ApprovalStatus
HAVING (HolidayRequests.ApprovalStatus = N'approved'))
WHERE a.StaffID = #staffID

Related

Query SQL Server using session variable

I'm trying to query a SQL Server database table based on a user variable (using ASP.NET and C#). I want to be able to pull just the user's unique records from the Waste Application Information table where the Farm Owner name is equal to the variable name (which is a string).
Here's part of my code:
conn.Open();
WasteAppData = "SELECT * FROM [WASTE APPLICATION INFORMATION] WHERE [FARM OWNER] = (user variable) ";
SqlCommand com = new SqlCommand(WasteAppData, conn);
GridView1.DataSource = com.ExecuteReader();
GridView1.DataBind();
If I replace the "(user variable)" with the actual value in the table column it does work correctly. Like this: 'Joe Smith' I've tried referencing the variable which is pulled from another webform with no luck... I think my syntax is incorrect? Any help would be great!
You need to do it this way:
WasteAppData = "SELECT * FROM [WASTE APPLICATION INFORMATION] WHERE [FARM OWNER] = #FarmOwn";
using (SqlCommand cmdSQL = new SqlCommand(WasteAppData , conn)
{
cmdSQL.Parameters.Add("#FarmOwn", SqlDbType.NVarChar).Value = strFarmOwnwer;
cmdSQL.Connection.Open();
GridView1.DataSource = cmdSQL.ExecuteReader;
GridView1.DataBind();
}
In this case "strFarmOwner" would be replaced with your actual variable that holds the value you want.

Counter variable not working Asp.net webform

I have a method to check if the id exists in a table and if it does insert into another database table; additionally I have label that will display the number of data entered. The query to insert into the database and select from the database works fine; but my problem is I'm not able to count, only receiving a count of 1 at all times. It is not incrementing; my question how do I get the counter to increment rather than just showing 1 at all times. This is what I have so far
protected void btnComplete_Click(object sender, EventArgs e)
{
string id = txtid.Text;
string user = lblUsername.Text;
string date = lblDate.Text;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString());
//commands identifying the stored procedure
SqlCommand cmd = new SqlCommand("selectId", conn);
SqlCommand cmd1 = new SqlCommand("CreateUserId", con);
// execute the stored procedures
cmd.CommandType = CommandType.StoredProcedure;
cmd1.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#id", id);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
cmd1.Parameters.Add("#id", SqlDbType.NVarChar).Value = barcode);
cmd1.Parameters.Add("#Username", SqlDbType.NVarChar).Value = user;
cmd1.Parameters.Add("#Date", SqlDbType.DateTime).Value = date;
counter = counter + 1;
}
reader.Close();
cmd1.ExecuteNonQuery();
lblCount.Text = counter.ToString();
}
else
{
lblError.Text = barcode + " does not exist!!";
}
}
Before you are asked for stored procedures and before giving you a concrete answer, you should fix some problems in your code
1) use using{} blocks with command and connection to make sure they are disposed.
2) In while loop, you are adding parameters to cmd1. Think what will happen if while loop runs more than 1 time!!
Now, if you want to show max in counter, just get max from database !!
In your cmd object you are sending some ID to stored procedure. It will always return 1 record if id is unique in your table.
So your counter is always 1
Solution
Not modifying much of your code, add count(id) as counter in your storedprocedure query returning result of cmd.
And in the while loop assign that to counter variable.
counter = Convert.ToInteger(reader[“counter”].ToString());
Above is not best solution though. As it will count records for all rows and will reduce performance over time.
For best solution, you need to make another command object that executes a query like select count(id) from YourTableName
This will give you number of records in your table.
Edit
From your comment.
You only want total records after inserting from cmd1.
Just do following:
1) In your storedProcedure for cmd 1, write Select Isnull(count(*),0) from YourTableNameHere
2) In your code, use ExecuteScalar instead of ExecuteNonQuery.
var result = cmd1.ExecuteScalar();
lblCount.Text = result.ToString();
Edit 2
You want to keep track of number of records inserted in current session. Use viewstate or session, depending on your requirement to save counter for session Or only untill user stays on current page.
var recordsAdded = cmd1.ExecuteNonQuery();
if(Session[“counter”] == null)
{
Session[“counter”] = 0;
}
if(recordsAdded>0)
{
Session[“counter”] = Convert.ToInteger(Session[“counter”]) + 1;
}
lblCount.Text = Session[“counter”];
Above will keep track of inserted records in session

My SqlDatareader was not working

I have a code for fetching customer_id and I use a SqlDataReader for reading customer_id from SQL Server. I test witch using breakpoint and step by step debugging and I understand the SqlDataReader condition was not compile and compiler jump straight in to the connection.close line:
string strQuery = "select customer_id from Registration where username=#username and password=#password";
SqlConnection connection1 = DBConnection.getConnection();
connection1.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection1;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
string customer_id = cmd.ExecuteScalar() as string;
connection1.Close();
if (customer_id == null)
{
Messages myMsg = new Messages();
myMsg.CreateMessageAlert("The User does not Registered or your using incorect username or password");
}
else {
Session["customer_id"] = customer_id;
}
Although the issue is not very clear, you can try to revise the code taking following into account:
There is no need to open/close db connection for every sql query in a method. Open it once, execute all queries, close. That will make code clear and faster.
As you take connection from somewhere else, make sure it is closed before you open it (Example: Check if SQL Connection is Open or Closed)
You run 2 queries and in both cases you get only 1 result (select count(*), select customer_id). Why then in first case you do ExecuteScalar() and ExecuteReader() in the other?
The other thought is there is no need to have 2 SqlCommand(), etc if you need to return results of 2 queries. Read about Retrieving Multiple Result Sets using NextResult
And last but not least - it seems you need to check if user is already registered and if true, get his id. Why not do it in one shot? The second query is good for both cases - if user does not exist, query will not return any result, if he does - his id will be returned. Doing this way, you would need only one query and less coding.
UPDATE:
The updated code looks more clear and straightforward, but you didn't get the point of my last comment. If you select count(customer_id) you get a count that you don't need. Why not simply select customer_id and check if it was returned or not?
Example:
//string strQuery = "select count(customer_id) from Registration where username=#username and password=#password";
string strQuery = "select customer_id from Registration where username=#username and password=#password";
SqlConnection connection1 = DBConnection.getConnection();
connection1.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection1;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
//int intRowCount = (int)cmd.ExecuteScalar();
string customer_id = cmd.ExecuteScalar() as string;
//txt1_username.Text = intRowCount.ToString(); <-- What's this?
connection1.Close();
//if (intRowCount == 1)
if (customer_id == null)
{
// user does not exist, because sql returned no rows
... <-- do something here
} else {
Session["customer_id"] = customer_id;
}
UPDATE #2:
To troubleshoot
Make sure txt1_username.Text and txt2_password.Text have expected values. It could be that you reset the Text somewhere and that could be the reason why the query returned no result. Try to hardcode the value in the code, for example,
cmd2.Parameters.AddWithValue("username", "admin");
cmd2.Parameters.AddWithValue("password", "123");
Copy-paste entire sql in Sql Server Management Studio (or other tool) and run it from here to ensure what result it returned.
Make sure you execute it against correct database (maybe you have different databases with same tables where data is different).
This is because your username is no longer the username. It is actually 1 because of the line
int intRowCount = (int) cmd.ExecuteScalar();
txt1_username.Text = intRowCount.ToString(); <-- RED FLAG
So in the inside the If, you are actually running
SELECT customer_id FROM registration WHERE username=1 and password=my_password
Comment line 15 and you should do fine.
updated
string strQuery = "select count(*) from Employee where FullName=#username";
SqlConnection connection = DBConnection.getConnection();
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = strQuery;
cmd.Parameters.AddWithValue("username", txt1_username.Text);
cmd.Parameters.AddWithValue("password", txt2_password.Text);
int intRowCount = (int)cmd.ExecuteScalar();
txt1_username.Text = intRowCount.ToString();
if (intRowCount == 1)
{
string strquery = "select customer_id from Registration where username=#username and password=#password";
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = connection;
cmd2.CommandText = strquery;
cmd2.Parameters.AddWithValue("username", txt1_username.Text);
cmd2.Parameters.AddWithValue("password", txt2_password.Text);
SqlDataReader reader = cmd2.ExecuteReader();
if (reader.Read())
{
string customerID = reader[0].ToString();
}
}
connection.Close();`
This is complete solution for your issue.
Do not need to open connection everytime. just make sure, connection is being closed once it's used.

using the querystring parameter in my where clause to generate insert operation

here,using request.Querystring i find the companyname and job title of particular Job.when user logsin using username in texbix.i want the Companyname,jobtitle and username in the same row of a table.But when i generate my query it inserts the (companyName & jobtitle) in the first row and username in second row.How can i fulfill my task.Some people said,i have to keep the companyname and jobtitle in a variable...then execute.
is it a parfect solution?
if it is,how can i do that?
code:
protected void ButtonApply_Click(object sender, EventArgs e) {
String str = Request.QueryString.Get("JobNo");
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
conn.Open();
string apply = "INSERT INTO Company (CompanyName,JobTitle) select CompanyName,JobTitle from Jobs where JobNo='"+str+"'" ;
SqlCommand insertApply = new SqlCommand(apply, conn);
try {
insertApply.ExecuteScalar();
conn.Close();
Response.Redirect("ApplyJob.aspx?JobNo="+str);
}
in the apply.aspx i have following code:
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
conn.Open();
string apply = "INSERT INTO Company (CandidateInformation) Values (#CandidateInformation)" ;
SqlCommand insertApply = new SqlCommand(apply, conn);
insertApply.Parameters.AddWithValue("#CandidateInformation", TextBoxaun.Text);
insertApply.ExecuteNonQuery();
conn.Close();
Response.Redirect("CompanyInfo.aspx");
Inserting two times will always result in two new rows.
You can do it all in the first insert statement:
string apply = "INSERT INTO Company (CompanyName,JobTitle, CandidateInformation) select
CompanyName,JobTitle, #CandidateInformation from Jobs where JobNo=#JobNo ;
SqlCommand insertApply = new SqlCommand(apply, conn);
insertApply.Parameters.AddWithValue("#CandidateInformation",
TextBoxaun.Text);
insertApply.Parameters.AddWithValue("#JobNo", str);
try
{
insertApply.ExecuteScalar();
conn.Close();
Response.Redirect("CompanyInfo.aspx");
}
Then you won't need the second page.
Use
Update Company Set CandidateInformation = #CandidateInformation where JobNo='"+str+"'" ;
instead of
string apply = "INSERTINTO Company (CandidateInformation) Values
(#CandidateInformation)" ;
If you will use Insert statement again, then it will always create new record in the table.
Update is used to update an already existing record of the table.

Oracle query/ stored procedure to return multiple resultsets

I am using oracle database. When I tried to fetch the data using a single select query, it returned a single table in the dataset.
How to write a select query or procedure in oracle, where I can get a dataset with 2-3(multiple) tables?
As far as I understood you question you would like to reduce the round trips to your database.
This can be done by a stored procedure in the following way:
http://msdn.microsoft.com/en-us/library/ms971506.aspx#msdnorsps_topic6
Package header:
CREATE OR REPLACE PACKAGE SELECT_JOB_HISTORY AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
);
END SELECT_JOB_HISTORY;
Package:
CREATE OR REPLACE PACKAGE BODY SELECT_JOB_HISTORY AS
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
)
IS
BEGIN
OPEN cur_JobHistory FOR
SELECT * FROM JOB_HISTORY
WHERE employee_id = p_employee_id;
END GetJobHistoryByEmployeeId;
END SELECT_JOB_HISTORY;
Client:
// create connection
OracleConnection conn = new OracleConnection("Data Source=oracledb;
User Id=UserID;Password=Password;");
// create the command for the stored procedure
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";
cmd.CommandType = CommandType.StoredProcedure;
// add the parameters for the stored procedure including the REF CURSOR
// to retrieve the result set
cmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;
cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =
ParameterDirection.Output;
// open the connection and create the DataReader
conn.Open();
OracleDataReader dr = cmd.ExecuteReader();
// output the results and close the connection.
while(dr.Read())
{
for(int i = 0; i < dr.FieldCount; i++)
Console.Write(dr[i].ToString() + ";");
Console.WriteLine();
}
conn.Close();
If you have to join these tables you can also use a normal join and split the result on the client (imho this is the way how a lot of ORMs do it).
This is exactly what I did, it was quite simple :
Database db = DatabaseFactory.CreateDatabase("ConnectionString");
object[] results = new object[3];
DbCommand cmd = db.GetStoredProcCommand("DATABASE.SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId",results);
DataSet ds = db.ExecuteDataSet(cmd);
DataTable dt1 = ds.Tables[0];
DataTable dt2 = ds.Tables[1];

Resources