Sql Conversion from nVarchar to int error - c#

Error:
Conversion failed when converting the nvarchar value 'select TopicID from Topic where TopicName='Data Structure'' to data type int
Code:
public void BindGridview()
{
string strConnString = ConfigurationManager.ConnectionStrings["infoConnectionString"].ConnectionString;
SqlConnection sqlcon = new SqlConnection(strConnString);
sqlcon.Open();
string strquery2 = "select TopicID from Topic where TopicName='" + ddltopic.SelectedItem.Text+ "'";
string strquery3 = "select i.name ,i.score from info as i,Topic as t where i.topic_id=#topicid";
SqlCommand cmd = new SqlCommand(strquery3,sqlcon);
cmd.Parameters.AddWithValue("#topicid",strquery2);
cmd.Connection = sqlcon;
SqlDataReader dr;;
this.GridView1.DataSource =cmd.ExecuteReader();
this.GridView1.DataBind();
sqlcon.Close();
}
}
Could anyone tell me where I am going wrong? Any help would be appreciated.. Please reply as soon as possible.. Thanks in advance..

You are passing the in the entire query not the topic id in this line here
cmd.Parameters.AddWithValue("#topicid",strquery2);
It is then taking that as a parameter and adding it to the following query. If this is a subquery, you can always execute it first and then use the result in the paramter.
But the reason that it is failing is because you are essentially trying to compare a String to an int by passing in the query string like that.

I think what you want in cmd.Parameters.AddWithValue("#topicid",strquery2); is the value returned by strquery2???? , the topic id will get generated if you execute this query first and the result of this will be used instead of query itself
Is that what you want ??

can you tried with below code, I have not tested but its should work for you
public void BindGridview()
{
string strConnString = ConfigurationManager.ConnectionStrings["infoConnectionString"].ConnectionString;
SqlConnection sqlcon = new SqlConnection(strConnString);
sqlcon.Open();
//Equal is not working when subquery return more records
string strquery2 = "select i.name ,i.score from info as i,Topic as t where i.topic_id in (select TopicID from Topic where TopicName=#TopicName)";
SqlCommand cmd = new SqlCommand(strquery2, sqlcon);
cmd.Parameters.AddWithValue("#TopicName", ddltopic.SelectedItem.Text);
cmd.Connection = sqlcon;
SqlDataReader dr; ;
this.GridView1.DataSource =cmd.ExecuteReader();
this.GridView1.DataBind();
sqlcon.Close();
}

Not an actual answer, but comments are too short for this.
This code is vulnerable to SQL injection:
string strquery2 = "select TopicID from Topic where TopicName='" + ddltopic.SelectedItem.Text+ "'";
Imagine that at some point in the future someone (you or someone else who is modifying your code) decides to replace the drop-down list with a combo box? Now imagine someone enters this text into the combo box:
'; TRUNCATE TABLE Topic; --'
Now your SQL server is going to do this:
select TopicID from Topic where TopicName = '';
TRUNCATE TABLE Topic; --'
Learn to use parameters.

Related

Issues with Increment MS-SQL, C#

I am having an issue with the increment for the ID. The ID would increase by one every time I click insert, but the problem occurs when the ID 2, it would insert the values twice, if ID 3, it would insert the values three times, and so on.
There are couple of options that I have been trying. One is Max and the other one is finding the last inserted value and add one to the ID just.
I would appreciate if anyone can help me out with this. Thanks
public partial class LoginInfo : System.Web.UI.Page
{
static string myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
private void GenerateID()
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery1 = "Select Count(S_ID) from Student_Name";
SqlCommand cmd = new SqlCommand(myQuery1, myConnection);
myConnection.Open();
int addOneS_ID_Table1 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneS_ID_Table1++;
lblstdID.Text = addOneS_ID_Table1.ToString();
myConnection.Open();
cmd.CommandText = "Select Count(P_ID) from Student_Pass";
int addOneP_ID_Table2 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneP_ID_Table2++;
lblstdPass.Text = addOneP_ID_Table2.ToString();
/*-----------------------------------------------------------------*/
//SqlConnection myConnection = new SqlConnection(myConnectionString);
//SqlCommand cmd = new SqlCommand("SELECT MAX(S_ID) as max_S_ID from Student_Name",myConnection);
//cmd.CommandType = CommandType.Text;
//myConnection.Open();
//lblstdID.Text = Convert.ToString(cmd.ExecuteScalar());
//cmd.CommandText = "SELECT MAX(P_ID) as max_P_ID FROM Student_Pass";
//lblstdPass.Text = Convert.ToString(cmd.ExecuteScalar());
//myConnection.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
GenerateID();
}
}
protected void btnInsert_Click(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery = "Insert into Student_Name(S_ID,STUDENT_NAME) VALUES" + "(#S_ID,#STUDENT_NAME)";
SqlCommand cmd = new SqlCommand(myQuery,myConnection);
cmd.Parameters.Add("#S_ID", SqlDbType.Int).Value = lblstdID.Text;
cmd.Parameters.Add("#STUDENT_NAME", SqlDbType.VarChar).Value = txtstdName.Text;
if(myConnection.State == ConnectionState.Closed)
{
myConnection.Open();
}
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
//Second Table
cmd.CommandText = "Insert into Student_Pass(P_ID,PASSWORD) VALUES" + "(#P_ID,#PASSWORD)";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#P_ID", SqlDbType.Int).Value = lblstdPass.Text;
cmd.Parameters.Add("#PASSWORD", SqlDbType.VarChar).Value = txtStdPass.Text;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
myConnection.Close();
GenerateID();
lblResult.Text = "Successfully Saved";
GridView1.DataBind();
}
}
Problem is with your query since you are getting COUNT(S_ID) which is going to get you count of records doesn't necessarily will give exact ID number. You should rather try MAX(S_ID) or ORDER BY clause saying
Select MAX(S_ID) from Student_Name
(OR)
Select TOP 1 S_ID from Student_Name ORDER BY S_ID DESC;
But recommended, You should actually go with SQL Server ##IDENTITY or SCOPE_IDENTITY() to get the last inserted record ID (assuming that S_ID is an IDENTITY column)
It's highly recommended to not use max or top in order to determine the "next" identifier to use, simply because of the cost associated with it.
However, there are some other pitfalls to using max and top especially if there is a chance that nolock is used (which is a whole other conversation). I've seen a lot of web applications use max and has proven to be a performance killer.
Rahul is right, ##identity or scope_identity are good alternatives. However, I think this calls for using a native SQL Server sequence, which was introduced in SQL Server 2012. It was something that application developers have been waiting for and Microsoft finally delivered.
The issue with using ##identity or scope_identity is that you actually have to write rows to some table before you can even contemplate doing something.
This makes it a bit more costly and messier than what it may need to be. In the case of using a sequence, you can issue a new sequence number and then decide what to do and once you decide what to do you're still guaranteed that you're the only one with that sequence number.
You would create a sequence like this. You should check out the documentation as well.
create sequence dbo.StudentIdSeq
as int -- this can be any integer type
start with 1 -- you can start with any valid number in the int, even negative
increment by 1;
go
Then you issue new sequence numbers by doing this ...
select next value for StudentIdSeq;
It may still be good to create a stored procedure with an output parameter that you can call from C# (which is what I would do). In fact you may want to take it a step further, in the case that you have a bunch of sequences, and create a slick stored procedure that will get a new sequence based on the type that is being requested from the caller.

Have to fetch data from database and enter into textbox

I have to fetch data from database and enter into textbox in my form.My Form has textboxes and gridview(for some textboxes alone).I have to fetch data from database based on selected grid view cell=PROJECTNAME and enter into other textboxes matching that criteria.
I have done my coding part for single textbox and its showing "{"ORA-00904: \"PRIME\": invalid identifier"}"
Kindly help me with the following
OracleConnection con = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["TEST"].ToString());
con.Open();
OracleCommand cmd = con.CreateCommand();
string prime = gdDisplay.SelectedRow.Cells[1].Text;
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = prime";
string str= cmd.ExecuteScalar().ToString();
txtDescription.Text = str;
You can do something like this
There is no need to keep calling .ToString() as getValue is already a string. and also need to take care that the string values has to be quoted in the '' single quotes.
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = 'prime'";
var str= cmd.ExecuteScalar();
We can just put a check to see if the value is null
if (str!= null) {
txtDescription.Text = str.ToString();
}
and apart from that you could use this as well
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = 'prime'";
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
txtDescription.Text = reader["DESCRIPTION"].ToString().Trim();
}
change
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = prime";
to
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = 'prime'";
You may get result by changing the query to
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = 'prime'";
i.e by adding quotes to the passing identifier. But it is not safe to do so and might expose to sql injection problems. For example if someone tries to search with a keyword like --> Where ProjectName = 'Anil's Project', note there comes three quotes causing confusion to the query
A safe way and a good practice from the beginning itself is using parameters. Its simple. Do like
cmd.CommandText = "Select DESCRIPTION FROM CMPPOJECT WHERE PROJECTNAME = #ProjectName";
cmd.Parameters.AddWithValue("#ProjectName", "prime"); // don't use additional quotes inside like "'prime'"
string str= cmd.ExecuteScalar().ToString();

Is this query to retrieve data from database correct?

I need to retrieve a value from a field in database. I have the used following code. but the value checkOrderId (which I need) shows the SQL string instead of the value from database. I don't know why it is doing so. Could somebody help me please?
string connectionString = "Data Source = xxyyzz;Initial Catalog = xyz; Integrated Security = True";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From" + tableName + "ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
//cmd.ExecuteNonQuery();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == checkOrderId)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
I am new and dont have reputation to answer my question immediately. With everybody's help, i got this one solved...Great help, thanx everybody...following is my code.
string connectionString = "Data Source = EAEDEV;Initial Catalog = GIS; Integrated Security = True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
string valueReturned = (string)cmd.ExecuteScalar();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == valueReturned)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
}
You need to execute the query and check the results, here you are just comparing a string with the query SQL.
Please see here
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson03
for a tutorial.
Your expectation of the result being set into checkOrderId is incorrect. In this instance checkOrderId is just the query to execute and not the actual result.
You need to read the value back from executing the command:
using (var connection = new SqlConnection(connectionString))
using (var comm = new SqlCommand("Select TOP 1 OrderID From [GIS].[SecondaryTraffic].[PotentialBackHauls] ORDER BY InsertDate DESC", connection))
{
connection.Open();
object result = comm.ExecuteScalar(); // This is the key bit you were missing.
if (result != null)
{
// You can cast result to something useful
int orderId = (int)result;
}
} // Both comm and connection will have Dispose called on them here, no need to Close manually.
ExecuteScalar returns the value in the first cell (ie, column 1 row 1) as an object that you can cast to a better type (depending on what type it was in the result-set schema).
If you need to read multiple values, you need to look at ExecuteReader.
There are also other ways of doing this using output parameters, but that would pollute the point of the answer.
You can add space to your query
"Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
Nota : I suggest you to use AddWithValue method with your parameter
string checkOrderId = "Select TOP 1 OrderID From #tableName ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
cmd.Parameters.AddWithValue("#tableName", tableName );
Link : http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlparametercollection.addwithvalue.aspx
You don't actually run your command anywhere. Instead of the commented-out cmd.ExecuteNonQuery, you should look into the ExecuteScalar method, which allows you to read back a single result value from a query - which is what your query returns.
Add
int i = (Int32) cmd.ExecuteScalar();
right after
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
then the variable i will contain the order id
No, this is not correct. You are comparing the variable orderId to your query string. I doubt that's what you want to do. I imagine you'd be better off calling cmd.ExecuteScalar() to retrieve the actual OrderID value. As noted by other answers, your query string is missing a space. But most importantly, it is bad practice to construct SQL queries in code. Although I can't see a security issue with this code, if you continue to use this method you will probably write code that is vulnerable to SQL injection. I recommend you learn to either use parameters or LINQ to build your queries.

to find max value from a given table in sql express

i am trying to retrieve latest data from my database table.
i am using max(columnName) but not having result to my liking.
i keep getting column name instead of any value
please help me out in this...
the code for retrieving max value is like this
dbConnection dbCon = new dbConnection();
con = dbCon.doConnection();
SqlCommand cmd = new SqlCommand();
String query = "select max(studentNo) from studentInfo;";
cmd.Connection = con;
cmd.CommandText = query;
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
String x=reader["studentNo"].ToString();
}
here the studentNo is the column name whose value i need to extract and it is of int type
while printing the string x on my application i get studentNo instead of the value.
now i am short of clue to solve the prob because i can't find anything wrong with the code.
do help me in this one
The problem is in the way you are accessing the value, you can change two things here. Either access the reader by index or name the column appropriately in the query.
select max(studentNo) as StudentNo from studentInfo;
Your query outputs one row and one column of data, so you might consider using ExecuteScalar() instead of ExecuteReader():
dbConnection dbCon = new dbConnection();
con = dbCon.doConnection();
SqlCommand cmd = new SqlCommand();
String query = "select max(studentNo) from studentInfo;";
cmd.Connection = con;
cmd.CommandText = query;
String x = cmd.ExecuteScalar().ToString();
You need to give alias to your select after applying aggregate function
i.e. select max(studentNo) as NO from studentInfo
and while reading it
String x=reader["NO"].ToString();
First you need to set the correct alias do the column:
select max(studentNo) as 'studentNo' from studentInfo;
And second, you may want to assign a database to the table:
select max(studentNo) as studentNo from databaseName..studentInfo;

System.Data.OleDb.OleDbException: Number of query values and destination fields are not the same

I received some help which I much appreciate to insert info into a database using paramaters as it is better practice I believe to do this.
I do however get the following error 'Number of query values and destination fields are not the same'. Not sure as to why it is happening.
The code seems perfectly fine and the database.
[WebMethod]
public void bookRatedAdd(string title, int rating, string review, string ISBN, string userName)
{
OleDbConnection conn;
conn = new OleDbConnection(#"Provider=Microsoft.Jet.OleDb.4.0;
Data Source=" + Server.MapPath("App_Data\\BookRateInitial.mdb"));
conn.Open();
OleDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO bookRated([title], [rating], [review], [frnISBN], [frnUserName])VALUES(#title, #rating. #review, #ISBN, #userName)";
//adding my parameters
cmd.Parameters.AddRange(new OleDbParameter[]
{
new OleDbParameter("#title", title),
new OleDbParameter("#rating", rating),
new OleDbParameter("#review", review),
new OleDbParameter("#ISBN", ISBN),
new OleDbParameter("#userName", userName),
});
cmd.ExecuteNonQuery();
conn.Close();
}
Advice perhaps as to why this error exist?
Kind regards
Arian
There is a . (period) instead of a , (comma) in your INSERT statement after the #rating parameter.
Change the . to comma.
INSERT INTO bookRated([title], [rating], [review], [frnISBN], [frnUserName])
VALUES(#title, #rating, #review, #ISBN, #userName)
I think this may be as simple as that a period has been put in place of a comma where the parameters are specified:
#rating. #review
should be:
#rating, #review

Categories

Resources