Unable to set parameter to select command using dataadapter - asp.net

Here's my code. I am not able to set TableName variable, it is throwing an exception
Must declare the table variable "#TableName"
public DataTable getAllDataFromTable(String TableName)
{
cmd.CommandText = "select * from #TableName";
cmd.Parameters.AddWithValue("#TableName", TableName);
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}

You cannot use a parameter in that fashion. The best way to implement what you are looking for is to use a string.Format() method to create your select statement. The only real draw back is the fact you open the method up to SQL Injection.
public DataTable getAllDataFromTable(String TableName)
{
cmd.CommandText = string.Format("select * from {0}", TableName)";
da.SelectCommand = cmd;
da.Fill(dt);
return dt;
}
Here is a similar thread.
Table name and table field on SqlParameter C#?

Related

SqlDataAdapter.Fill running SQL command twice

I'm trying to insert a new row in my SQL database from ASP.NET but it's inserting the row twice instead of once.
I haven't been able to find which line of the code below is causing this.
Here's my code:
public static void Register(User user)
{
string query = "insert into TblTutors (username,email,pass,sub,category,city,fullname,img,bio,tutor,way)
values (#username,#email,#pass,#mat,#cat,#country,#fullname,Cast(#img As nvarchar(MAX)),#bio,#tutor,#way )";
using (SqlCommand cmd = new SqlCommand(query, con))
{
cmd.Parameters.AddWithValue("#username", user.username);
cmd.Parameters.AddWithValue("#email", user.email);
cmd.Parameters.AddWithValue("#tutor", user.tutor);
cmd.Parameters.AddWithValue("#way", user.way);
cmd.Parameters.AddWithValue("#mat", user.mat);
cmd.Parameters.AddWithValue("#cat", user.cat);
cmd.Parameters.AddWithValue("#country", user.country);
cmd.Parameters.AddWithValue("#pass", "halima");
cmd.Parameters.AddWithValue("#fullname", user.fullname);
cmd.Parameters.AddWithValue("#img", user.img);
cmd.Parameters.AddWithValue("#bio", user.bio);
con.Open();
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
int i = cmd.ExecuteNonQuery();
con.Close();
}
}
DataAdapter.Fill is used to populate a DataSet with the results of the SelectCommand of the DataAdapter.
Since you're not looking to do any SELECT queries, remove the code regarding filling the DataTable as while it won't return any data, it will execute your INSERT, UPDATE and DELETE SQL commands inside cmd passed to new SqlDataAdapter(cmd);.
You're essentially writing data twice, once when you fill dt & again when you execute the query:
sda.Fill(dt);
...
int i = cmd.ExecuteNonQuery();
This should work as expected, removing the need for a DataSet as well.
public static void Register(User user)
{
string query = "insert into TblTutors (username,email,pass,sub,category,city,fullname,img,bio,tutor,way)
values (#username,#email,#pass,#mat,#cat,#country,#fullname,Cast(#img As nvarchar(MAX)),#bio,#tutor,#way )";
using (SqlCommand cmd = new SqlCommand(query, con))
{
cmd.Parameters.AddWithValue("#username", user.username);
cmd.Parameters.AddWithValue("#email", user.email);
cmd.Parameters.AddWithValue("#tutor", user.tutor);
cmd.Parameters.AddWithValue("#way", user.way);
cmd.Parameters.AddWithValue("#mat", user.mat);
cmd.Parameters.AddWithValue("#cat", user.cat);
cmd.Parameters.AddWithValue("#country", user.country);
cmd.Parameters.AddWithValue("#pass", "halima");
cmd.Parameters.AddWithValue("#fullname", user.fullname);
cmd.Parameters.AddWithValue("#img", user.img);
cmd.Parameters.AddWithValue("#bio", user.bio);
con.Open();
int i = cmd.ExecuteNonQuery();
con.Close();
}
}

Choose between two SQL statements using CASE or something else

I have a dropdown and I want to check the selected value first before I run my SQL command so here is my logic: if the selected value of the dropdown is not 'ALL' then I want to run this sql statement:
select distinct Location
from myTable
where PROGRAM = '"+program+'"
else if selected value of the dropdown is set to 'ALL' then I want to run this SQL command instead:
select distinct Location
from myTable
Here is my my code which works fine but not the way I want it to work. How can I modify the SQL command so I can check the condition that I mentioned above? Thanks
protected void BindServiceList(DropDownList ddlService)
{
DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");
string program = ddl.SelectedValue;
String strConnString = System.Configuration.ConfigurationManager
.ConnectionStrings["myConn"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
SqlDataAdapter sda = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("select distinct LOCATION" +
" from myTable where PROGRAM = '" + program + "' ");
cmd.Connection = con;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
con.Close();
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
Don't change your SQL command instead create different SQL command's text based on the condition. Also you should use SqlParameter instead of string concatenation. Your code is prone to SQL injection. Consider enclosing your connection and command object in using statement as that will ensure resource disposal at the end of block.
using (SqlConnection con = new SqlConnection(strConnString))
{
SqlDataAdapter sda = new SqlDataAdapter();
using (SqlCommand cmd = new SqlCommand())
{
if (program.Equals("All", StringComparison.InvariantCultureIgnoreCase))
{
cmd.CommandText = "select distinct LOCATION from myTable";
}
else
{
cmd.CommandText = "select distinct LOCATION from myTable WHERE PROGRAM = #program";
cmd.Parameters.AddWithValue("#program", program);
}
cmd.Connection = con;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
con.Close(); // can be left out because of `using` statement
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
}
Do this:
protected void BindServiceList(DropDownList ddlService)
{
DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");
string program = ddl.SelectedValue;
String strConnString = System.Configuration.ConfigurationManager
.ConnectionStrings["myConn"].ConnectionString;
using (var con = new SqlConnection(strConnString) )
using (var cmd = new SqlCommand("select distinct LOCATION from myTable where PROGRAM LIKE #Program", con) )
{
//guessing at column type/length here
cmd.Parameters.Add("#Program", SqlDbType.NVarChar, 20).Value = program;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
}
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
Notice that I fixed your sql injection vulnerability! Also notice that I changed the = to a LIKE. Then you can set the value property for the All item in the ddlProgram control to: %. (See the AppendDataBoundItems property if you need help getting that working with a databound ddl). Using that wildcard with the LIKE operator will result in the query returning all locations.
Firstly Parameterize your query.
Since there are already solutions using c#. I will propose a SQL solution.
You could do a Case in your WHERE CLause by passing a parameter that suggests if the dropdown value is ALL.
Something like:
SELECT DISTINCT Location
FROM myTable
WHERE (
CASE
WHEN #IsAllSelected = 0
THEN PROGRAM
WHEN #IsAllSelected = 1
THEN 1
END
) = (
CASE
WHEN #IsAllSelected = 0
THEN #Your_program_value
WHEN #IsAllSelected = 1
THEN 1
END
)

Return a string Value from SQL Server stored procedure

I have the following method and stored procedure.
My question is how to return a string value from stored procedure to use in addStaffName method ?
public string addStaffName()
{
string staffName = string.Empty;
string sConnectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
SqlConnection SqlCOn = new SqlConnection(sConnectionString);
SqlCommand SqlCmd = new SqlCommand();
SqlCOn.Open();
SqlCmd.Connection = SqlCOn;
SqlCmd.CommandType = CommandType.StoredProcedure;
SqlCmd.CommandText = "FetchStaffName";
SqlCmd.Parameters.AddWithValue("email", email);
//???
return staffName;
}
create procedure fetchStaffName
#email varchar(100)
AS
begin
select (employeeName)
from employee
where email = #email
end
If you can be sure that you'llonly ever get one row, one column as a result set - then you can use .ExecuteScalar() on your SqlCommand like this:
string staffName = string.Empty;
string sConnectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
using (SqlConnection sqlCon = new SqlConnection(sConnectionString))
using (SqlCommand sqlCmd = new SqlCommand("FetchStaffName", sqlCon)
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#email", email);
sqlCon.Open();
staffName = sqlCmd.ExecuteScalar().ToString();
sqlCon.Close();
return staffName;
}
I also put the usage of SqlConnection and SqlCommand into using() { ... } blocks which is the recommended best practice for anything that's deriving from IDisposable to ensure proper disposal of the objects after their use
Consider to make fetchStaffName a scalar function rather than stored procedure. By definition stored procedures are required to perform a set of actions with data. Scalar function guarantees there will be exactly one output value for the set of input values.
CREATE FUNCTION fetchStaffName (
#email VARCHAR(100)
)
RETURNS VARCHAR(?) --Place the length of employeeName field instead of ? symbol.
BEGIN
RETURN (SELECT employeeName FROM employee WHERE email = #email)
END
And then your .NET code transforms into the following:
using (SqlConnection SqlCOn = new SqlConnection(sConnectionString))
{
SqlCommand SqlCmd = new SqlCommand("SELECT fetchStaffName(#email)", SqlCOn);
SqlCmd.CommandType = CommandType.Text;
SqlCmd.Parameters.AddWithValue("#email", email);
SqlCOn.Open();
staffName = (string)SqlCmd.ExecuteScalar();
}
As you can see CommandType changed from StoredProcedure to Text. I also wrapped the work with SqlConnection object into using construction to dispose its resources and close automatically.

Reading SQL Server database using datasource

I have created a datasource to connect with SQL Server database. It works fine when I connected it with GridView. I need to read certain item (say FirstName) and store the value to a variable.
How can I use this datasource? Could you give me the statements for that?
Thanks
The SqlDataSource is intended as what the name implies - a data source for data binding. It is not a way to get individual values from a database table.
If you need to read a single value, you should use straight ADO.NET - SqlConnection and SqlCommand - to read that value - something like:
string sqlStmt = "SELECT FirstName FROM dbo.YourTable WHERE ID = #ID";
using(SqlConnection conn = new SqlConnection(your-connection-string-here-))
using(SqlCommand cmd = new SqlCommand(sqlStmt, conn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = 4044;
conn.Open();
string firstName = cmd.ExecuteScalar().ToString();
conn.Close();
}
The ExecuteScalar call works only if you want to read a single row, single column value - like here. Otherwise you need to use either the SqlDataReader, or use the DataTable and a SqlDataAdapter to fill that data table (if you have multiple rows).
Update: if you want to use a SqlDataAdapter instead - do this:
public DataTable LoadData()
{
DataTable result = new DataTable();
string sqlStmt = "SELECT ID, FirstName, LastName, Country " +
"FROM dbo.YourTable";
using(SqlConnection conn = new SqlConnection(your-connection-string-here-))
using(SqlCommand cmd = new SqlCommand(sqlStmt, conn))
{
SqlDataAdapter dap = new SqlDataAdapter(cmd);
dap.Fill(result);
}
return result;
}
When you call this method, you'll get back a DataTable that contains the columns you've defined in your SQL statement, and all rows from the database table.
DataTable myData = LoadData();
Now, you can iterate over the rows and get the FirstName value for each row:
foreach(DataRow row in myData.Rows)
{
string firstName = row["FirstName"].ToString();
// do whatever you need to do with the first name
}

How can I execute multiple database requests in ASP.NET C#?

In every ASP.NET application I have written, I would make number of request to the database before outputting the information onto the web page.
For example:
var DataTable1 = GetDataTable("Select * From Customers");
var DataTable2 = GetDataTable("Select * From Products");
var DataTable3 = GetDataTable("Select * From Orders");
As far as I'm aware, the code above would make 3 separate trips to the database and would do them one after the other.
Is there anyway I can gather together my parameterized SQL statements and make only 1 trip to the database server?
var SqlString = "SELECT * FROM Customers; SELECT * FROM Products; SELECT * FROM ORDERS;");
var ds = GetDataSet(SqlString);
var DataTable1 = ds.Tables(0);
var DataTable2 = ds.Tables(1);
var DataTable3 = ds.Tables(2);
My solution:
SqlConnection con = new SqlConnection("Server=CLASS-III-WKS10\\SQLEXPRESS;Initial
Catalog=wind;Integrated Security=True");
int[] id=new int[9];
int i = 0;
page_load()
{
con.Open();
SqlCommand cmd = new SqlCommand("select *from windmill", con);
SqlDataReader rd = cmd.ExecuteReader();
while (rd.Read())
{
id[i] = rd.GetInt32(9);
i++;
//MessageBox.Show(id.ToString());
}
rd.close();
SqlCommand cmd1 = new SqlCommand("Update windmill set State='Stopped',PmState='Not Available'where Id=0", con);
cmd1.ExecuteNonQuery();
}
Use semi-colons to separate SQL statements and reader.NextResult to get each set. Your code will end up looking something like this.
Using con As New SqlConnection
Using cmd As New SqlCommand("Select * From Customers; Select * From Products; Select * From Orders")
Using reader = cmd.ExecuteReader
Dim dt1 As DataTable
dt1.Load(reader)
reader.NextResult()
Dim dt2 As DataTable
dt2.Load(reader)
reader.NextResult()
Dim dt3 As DataTable
dt3.Load(reader)
End Using
End Using
End Using
Create a Thread class and place a method in that class which accept string query as input:
then create a Thread object and start the object.
Check this out http://msdn.microsoft.com/en-us/library/aa645740(VS.71).aspx

Resources