Executing query in c# asp.net - asp.net

I've created a query to select the body of a message from the message database. I'm not sure how to execute it to get the body string back and store it. I've tried using ExecuteReader, ExecuteScalar, and ExecuteNonQuery. None of them work. ExecuteScalar was the closest to working but it only returned the body of the message of the first row no matter which row you were trying to view. Anyone know how to do this? It's gotta be a easy fix.
SqlCommand com = new SqlCommand("SELECT Body FROM Messages WHERE MessageID= MessageID", conn);
com.Connection = conn;
com.Connection.Open();
String body;
body = com.ExecuteScalar.ToString;
That's what I have now. Thanks in advance!

What is messageId in your query? You should be doing something like this
SqlCommand com = new SqlCommand("SELECT Body FROM Messages WHERE MessageID = #MessageId");
com.Parameters.AddWithValue("#MessageId", 1); //Replace 1 with messageid you want to get
string s = com.ExecuteScalar().ToString()

You can use SQLDataAdapter and Datatable for this :
SqlCommand com = new SqlCommand("SELECT MessageID,Body FROM Messages WHERE MessageID= MessageID", conn);
SqlDataAdapter dadapter=new SqlDataAdapter();
DataTable dt = new DataTable();
com.Connection = conn;
com.Connection.Open();
String body;
dadapter.SelectCommand=com;
dadapter.Fill(dt);
body = dr.Rows["Body"].toString();

you should try something like this.
SqlCommand com = new SqlCommand("SELECT Body FROM Messages WHERE MessageID= MessageID", conn);
com.Connection = conn;
com.Connection.Open();
String body;
SqlDataReader dr = com.ExecuteReader();
if(dr.HasRows){
while(dr.Read()){
body+=dr["Body"].ToString();
}
}
I hope this works for you.

Based on your reply to Nudier below, you're trying to pass in the messageID of the selected message by using WHERE MessageID = MessageID
The reason this won't work, and the reason you're always getting the first row returned is that SQL doesn't know that MessageID is a variable you're trying to pass in. As far as SQL knows, MessageID is a column name, so all you're asking SQL to do is select the column "Body" of the row where the column MessageID = the column MessageID, so where MessageID equals itself, which always equates to true. And since ExecuteScalar always returns the first cell of the first row, your query will always return all rows from the Messages table, and the executeScalar will grab the first cell.
Hopefully that made sense, if not, just copy your query and run it against your SQL database, you should see what I mean about it returning all rows as the where clause always equals true.
To fix it, you need to take into account what Anuraj said about adding a parameter.
To pass in a variable to a SQL string in code, you need to parameterise it, then add the relevant parameter, so your SQL should become:
SELECT Body FROM Messages WHERE MessageID=#MessageID
(Notice the addition of the # symbol before the parameter name?)
And directly below that line, you need to add the parameter in code using:
com.AddParameterWithValue("#MessageId", MessageId);
(I think that's right, I copied it from Anuraj, I normally do it slightly differently)
Again, to see this working, you can run it directly against the database with a parameter by using
DECLARE #messsageID AS INTEGER
SET #messageID = 1
SELECT Body FROM Messages WHERE MessageID=#messageID
Have a read of this for more details (or if I haven't managed to be entirely clear) http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06

Related

Unable to update database with the Window Form Application

I am trying to update my database with the window form I have created, however an error occurred when I execute the code:
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Data.dll" at comm.ExecuteNonQuery();
Here is the code that I used to connect to my database. Was the code I used to update the database wrong?
string conn=ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
SqlConnection connection = new SqlConnection(conn);
SqlCommand comm = new SqlCommand("UPDATE ExerciseInstruction SET Accumulated_Daily_Sets_Completed = '0' WHERE ExerciseInstructionsID ='" + exerciseInstructionID +"'", connection);
comm.ExecuteNonQuery();
Here is the complete error message :
ExecuteNonQuery requires an open and available Connection. The
connection's current state is closed.
The error message explain all. The command cannot be executed if the code doesn't know how to reach the database. Just a call to connection.Open should fix the problem, however I think you need to use a proper way to execute the query.
This is called Parameterized query. In this way you don't concatenate strings together to form you query text but use parameters to pass values to the database engine and a special formatted string containing the parameters placeholders.
There are two main advantages to do so. It is not possible to target your code with Sql Injection hacks and you don't have to handle quoting around your strings (an infinite source of bugs)
string conn=ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
string cmdText = #"UPDATE ExerciseInstruction
SET Accumulated_Daily_Sets_Completed = 0
WHERE ExerciseInstructionsID =#exid";
using(SqlConnection connection = new SqlConnection(conn))
using(SqlCommand comm = new SqlCommand(cmdText, connection))
{
connection.Open(); // Need this before executing the query
comm.Parameters.Add("#exid", SqlDbType.Int).Value = exerciseInstructionID;
comm.ExecuteNonQuery();
}

What is wrong with the following query?

I have a table containing name, surname and email. I want to retrieve them from the table and so i write:
if (LoginAs.SelectedValue == "Administrator")
{
string result;
string query = "Select * from AdminTable where ID='"+ idBox.Text +"'";
cmd1 = new SqlCommand(query, con);
result = Convert.ToString(cmd1.ExecuteScalar());
Response.Redirect("Admin.aspx");
//Admin user = new Admin(idBox.Text, "Active", mail, firstName, LastName, passwordBox.Text);
}
The problem is, it only returns the name field of the specified row even though i wrote "Select *". What is wrong here?
ExecuteScalar returns just the first column of the first row, and ignores the rest.
So you should use ExecuteReader method. An example from MSDN:
using (SqlConnection connection = new SqlConnection(
connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(String.Format("{0}", reader[0]));
}
}
Note that the while (reader.Read()) checks whether your query returned (more) results and positions the cursor on the next record, that you can then read. This example prints the first column's value.
The using statement makes sure the connection is closed after use, whatever happens.
Also, don't build your query directly with input from the user (such as the value of a TextBox), use parameters instead to prevent SQL injection attacks.
You must try ExecuteReader() instead of using ExecuteScalar()
ExecuteScaler is used in situation where we have to read a single value.eg:
select count(*) from tablename.
while
ExecuteReader is used for any result set with multiple rows/columns
(e.g., SELECT * from TableName)
Sample code:
string myQuery="Select * from AdminTable where ID=#myid";
SqlCommand cmd=new SqlCommand(myQuery,conn);
cmd.Parameters.AddWithValue("#myid", value);
conn.Open();
SqlDataReader dreader;
dreader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dreader.Read())
{
string Value1= dreader["COl1"].ToString();
string Value2= dreader["COl2"].ToString();
}
dreader.Close();
Always use parameterized Query
You may try cmd1.ExecuteReader() instead.

Update database row where there is a certain value

I need to update a row where there exists a certain value. The ExecuteNonQuery returns a 0 meaning the database is not being updated. When stepping through in debug, the update is hit and contains the correct values, however no updates are being done.
string verifySql = #"UPDATE UserInfo SET Verified='#Verified'
WHERE UserID='#UserID'";
using (var con = newSqlConnection(
ConfigurationManager.ConnectionStrings["UserInfoDB"].ConnectionString))
using (var cmd = new SqlCommand(verifySql, con))
{
con.Open();
cmd.Parameters.AddWithValue("#Verified", "Verified " + DateTime.Now);
cmd.Parameters.AddWithValue("#UserID", user.UserId);
Response.Write(cmd.ExecuteNonQuery());
con.Close();
}
Lose the single quotes around the parameter names in your sql statement. You don't need them, and they're making your code interpret your parameter placesholders as simple string literals.
Then remove the con.Close() line. You don't need that either; it's covered by the using block.
Finally, you might also consider changing your verified column to a simple DateTime type, rather than trying to store that data as text.

Return Two Data Sets

So I'm passing a ClientID to my DB and using that to look up all their details, then I want to use those details to also get all other users closely matching the details. I have all this written but my problem is I want to return the initial user's details also. For example;
Select Details = #UserDetails
from UnregisteredUserTable
where UserId = #UserID
Select BunchOfUsersWithMatchingData
from RegisteredUserTable
where UserDetails like #UserDetails
Obviously I've removed unnecessary info. But as you can see this returns all the data of the matching users but not the initial user's details. Could I use a CTE somehow?
UPDATE
Apologies, no idea my data access mattered. I'm doing pretty much the following atm but can change it no problem.
Dim results = thisObjectContext.MatcherSP(UserID)
For Each obj In results
TableData.Rows.Add(obj.IdNumber, obj.name,
obj.emailaddress1, obj.telephone1, obj.telephone2, obj.address1_line1,
obj.address1_line2)
Next
UPDATE 2
ok so I'm just using the two selects in my SP and it runs fine in SQL Server. But when I try to add it to my dbml in Visual Studio I get a strange error:
Unable to extract stored procedure 'dbo.MySP' because its result set contains muultiple anonymous columns.
Any ideas about that?
Well, this isn't VB code, but I will keep it as simple as possible.
Use a SqlDataAdapter to fill a data set. Results from both your select statements will populate different tables in the the DataSet.
cmd.CommandText = "MatcherSP";
cmd.CommandType = CommandType.StoredProcedure;
adapter = new SqlDataAdapter(cmd);
ds = new DataSet();
adapter.Fill(ds);
You can then access the data as follows:
tableA = ds.Tables[0];
tableB = ds.Tables[1];
You can use the SqlDataReader's nextresult() method.
using(SqlCommand cmd = new SqlCommand("NameOfSP",c))
{
cmd.CommandType = CommandType.StoredProcedure;
using(SqlDataReader d = cmd.ExecuteReader())
{
while(d.Read()){
//Result data from the first select
}
d.NextResult();
while(d.Read()){
//Result data from the second select
}
}
}
http://twogeeks.mindchronicles.com.dnpserver.com/?p=28&cpage=1#comment-37818
Brilliant article, outlined very clearly exactly what I wanted to do.

System.Data.SqlClient.SqlException: Invalid column name

Trying to do a recordset, I just want one column of data, but this code is giving me an error.. I'm an ASP.NET newb, can anyone help?:
System.Data.SqlClient.SqlException: Invalid column name
'CustomerName'.
using (SqlConnection con = new SqlConnection(DB.GetDBConn()))
{
con.Open();
using (IDataReader dr = DB.GetRS("select CustomerName from Customer where CustomerID=" + Customer.CustomerID, con))
{
string CustomerName = "CustomerName";
}
}
String EncCustomerName = Encrypt(CustomerName.Replace(".", "").Replace("-", ""),"1");
Question #2: How do I bind the database content to the CustomerName string? It seems like its only returning "CustomerName" as the value for CustomerName string.. I would like it to return the database data for CustomerName string.. Help?
Suggested to use a ExecuteScalar, so i modified the request to this
using (var con = new SqlConnection(DB.GetDBConn()))
using (var cmdContrib = new SqlCommand("SELECT CustomerName FROM Customer WHERE CustomerID=" + ThisCustomer.CustomerID, con))
{
con.Open();
string CustomerName = cmdContrib.ExecuteScalar();
}
And i Get this error:
"string CustomerName = cmdCust.ExecuteScalar();"
CS0266: Cannot implicitly convert type 'object' to 'string'. An explicit conversion exists (are you missing a cast?)
To answer your second question:
// Set it here so you can access it outside the scope of the using statement
string CustomerName = "";
using (SqlConnection con = new SqlConnection(DB.GetDBConn()))
{
con.Open();
using (IDataReader dr = DB.GetRS("select CustomerName from Customer where CustomerID=" + Customer.CustomerID, con))
{
while (dr.Read())
CustomerName = dr["CustomerName"].ToString();
}
}
}
If you're sure you'll only get one CustomerName result, using a DataReader is a bit of an overkill.
SqlCommand.ExecuteScalar Example
string CustomerName = "";
using (SqlConnection con = new SqlConnection(DB.GetDBConn()))
{
SqlCommand cmd = new SqlCommand("SELECT CustomerName FROM Customer WHERE CustomerID = " + Customer.CustomerID, con);
cmd.CommandType = CommandType.Text;
con.Open();
CustomerName = Convert.ToString(cmd.ExecuteScalar());
}
SqlCommand.ExecuteScalar Method
Additional Info
ExecuteScalar returns an object, so you'll need to convert the returned value to the proper type (in this case, string).
Also, you should declare your CustomerName value outside of the using blocks (as I did in my example) - otherwise it will be scoped to the using blocks and not available outside of them.
It means that either CustomerName or CustomerID is not a valid column within your database. Check your table again.
Make sure you are trying to connect correct database.
See CustomerName column should be in Customer table. check spelling also
First, debug and check the value of:
DB.GetDBConn()
You will verify that you are going to the same in Studio as you are in the program.
I think it is the spelling somewhere between the db and your code.
Once you get past the error, you need to fix this:
{
string CustomerName = "CustomerName";
}
You are not accessing the reader, try some kind of tutorial for that stuff.
Try doing a select * from customer where ... and put a breakpoint on your using datareader statement. Then use quick-watch on the datareader object to investigate the columns exposed in the recordset.
Or you could run the select statement on your db of choice to ensure that the column name is the same.
I agree with Madhur above, your column name is not spelled correctly. Or you are not connecting to the correct db.
Hope this helps

Resources