C# - Web Site - SQL Select Statement - c#

I want to use a select statement to find if there is a record that already exists. I've put the code below but it throws an error at the dReader = comm.ExecuteReader(); and i'm unsure why. Any help?
string connString = "Data Source=KIMMY-MSI\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True";
SqlDataReader dReader;
SqlConnection conn = new SqlConnection(connString);
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
comm.CommandText = "SELECT * FROM Customers WHERE CustomerID == " + txtID.Text;
comm.Connection.Open();
dReader = comm.ExecuteReader();
if (dReader.HasRows == true)
{
Response.Write("Exists");
}
The error:
Invalid Column Name (whatever I input)
It seems to be looking for a column named what I input rather than looking for the actual data.

Change your == to =. That is invalid SQL as it is.
Also if txtID.Text is non-numeric then it needs to be in single quotes. You should not be constructing your SQL like this, instead use a parameter:
comm.CommandText = "SELECT * FROM Customers WHERE CustomerID = #CustomerID";
comm.Parameters.AddWithValue("CustomerID", txtID.Text);
More Info
C# using statement
SQL reference
SQL injection (why you should parameterize your queries)

It looks like your command has an issue:
SELECT * FROM Customers WHERE CustomerID == 1
In SQL you don't need to use the == operator to ensure something is equal to another.
Try:
SELECT * FROM Customers WHERE CustomerID = 1
In addition, you might want to read up about SQL Injection, the way you are binding the value is directly from a textbox value. This has a huge security hole which could lead to arbitrary sql command execution.

Change this line:
comm.CommandText = "SELECT * FROM Customers WHERE CustomerID == " + txtID.Text;
To this line:
comm.CommandText = "SELECT * FROM Customers WHERE CustomerID = #id";
comm.Parameters.AddWithValue("id", int.Parse(txtID.Text));
Assuming that your customer id is int on the database.

The equals operator in SQL is just a single =.
Also, you really shouldn't be concatenating SQL queries like that, you are just opening yourself up to SQL Injection attack. So change it to be like this:
comm.CommandText = "SELECT * FROM Customers WHERE CustomerID = #CustomerId";
comm.Parameters.AddWithValue("#CustomerId", txtID.Text);
See Stop SQL Injection Attacks Before They Stop You on MSDN.

You are using invalid SQL. You name to change "==" to "=".
You should also consider wrapping your IDisposable objects in using statements so that unmanaged objects are properly disposed of and connections are properly closed.
Finally, think about using parameters in your SQL, instead of concatenating strings, to avoid SQL injection attacks:
string connString = #"Data Source=KIMMY-MSI\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True";
string sql = "SELECT * FROM Customers WHERE CustomerID = #CustomerID";
using (SqlConnection conn = new SqlConnection(connString))
using (SqlCommand comm = new SqlCommand(sql, conn))
{
comm.Connection.Open();
comm.Parameters.AddWithValue("#CustomerID", txtID.Text);
using (SqlDataReader dReader = comm.ExecuteReader())
{
if (dReader.HasRows == true)
{
Response.Write("Exists");
}
}
}

Related

C# SQL pass variable to query

I am currently writing a Search function that bring down a value Name
Here is my query:
"SELECT Company.Name, Company.Reg FROM Company WHERE Name LIKE '%''" + Name + "''%'";
Here is the function:
public object CompanySearch(string Name)
{
using (PCE)
{
SqlConnection con = new SqlConnection(constr);
try
{
List<CompanySearch> cm = new List<CompanySearch>();
SqlCommand command = new SqlCommand();
command.Connection = con;
"SELECT Company.Name, Company.Reg FROM Company WHERE Name LIKE '%''" + Name + "''%'";
con.Open();
//process the sql execute etc
}
}
}
Is the way I reading Name correctly?
I tested without ' ' , however I get an exception message as follow:
"ExceptionMessage": "Incorrect syntax near 'Mysearch'.",
UPDATE
SELECT Company.Name, Company.Reg
FROM Company
WHERE CompanyName LIKE '%MySearch%';
This is the code that I execute in SSMS, and it went sucess.
However it doesnt work on my C#
First of all, you should always avoid to "manually build" your own query. This is the best way to have SQL Injection (https://en.wikipedia.org/wiki/SQL_injection)
Secondary, you should used Parameter in your query
SqlCommand cmd = new SqlCommand("SELECT Company.Name, Company.Reg WHERE Name LIKE #companyName", connection);
cmd.Parameters.Add("#companyName", SqlDbType.NVarChar).Value = Name;
But in 2020, you should use an ORM instead of building your own query. This is far better to save time and avoid bugs.
Have a look at EF Core (https://learn.microsoft.com/fr-fr/ef/) or Dapper (https://stackexchange.github.io/Dapper/), ...
This is what I try, it worked for me...
public object CompanySearch(string Name)
{
SqlConnection con = new SqlConnection(constr);
try
{
List<CompanySearch> cs = new List<CompanySearch>();
SqlCommand command = new SqlCommand();
command.Connection = con;
command.CommandText = "SELECT Name, Reg, FROM Company WHERE Name LIKE '%" + Name + "%'";
con.Open();
//process the sql execute etc
}
}
}
However, a good practice is to parameterize your query that mentioned by #HoneyBadger

SqlDataAdapter, SqlCommand dropping the leading numbers from string

I am trying to execute a SQL statement with a where clause which looks like
string s2 = "Select * from idtyfile where oysterid=" + id ;
SqlCommand da2 = new SqlCommand(s2, con); or
SqlAdapter da2 = new SqlAdapter(s2, con);
Both of these are failing when I am trying to execute them
da2.ExecuteReader();
the data in ID looks like
ID
43PCOU5T
ZP6RAEJ0
For some reason both of these queries are failing on these kind of data.
You are missing the single quotes in your select command which is what is making your original SELECT fail. However I would like to note that you should always parameterize and encapsulate your SqlCommand / SqlConnection in a using statement. The following would be a cleaner more secure way to solve your problem.
string s2 = "Select * from idtyfile where oysterid=#id";
DataTable myDataTable = new DataTable();
using (SqlConnection conn = new SqlConnection(myConnectionString))
using (SqlCommand cmd = new SqlCommand(s2, conn))
{
cmd.Parameters.AddWithValue("#id", id);
conn.Open();
myDataTable.Load(cmd.ExecuteReader());
}
For some educational resources, you should look at the following links.
MSDN Reference for the using keyword
MSDN Reference for SqlCommand -- Look at the Parameters property.

SQL Server select query execution from c#

string user = "1234";
string strSQL = string.Format("Select * From User where UserId = '{0}'",user);
SqlCommand myCommand = new SqlCommand(strSQL, cnn);
reader = myCommand.ExecuteReader();
My User table consists of UserId and Password columns. The UserId column type is nchar and so I've used the single quotes. I get an error saying that
incorrect syntax near the keyword User"
(I guess the table name User is being referred to here).
I have the connection string and other database environment related things correctly for I've checked the database connection status and it is open(during program execution).
What is the error in the syntax? I'm unable to retrieve the rows from my table.
User is a Keyword. Use square bracket around it to avoid the error. Select * from [User]
string strSQL = string.Format("Select * From [User] where UserId = '{0}'",user);
Also, you should always use parameterized query like below to prevent SQL Injection attack:
string strSQL = string.Format("Select * From [User] where UserId = #UserId");
You should really use parameters for this:
string user = "1234";
using (SqlCommand command = new SqlCommand("select * from [User] where UserId = #userid", cnn))
{
command.Parameters.AddWithValue("#userid", user);
using (SqlDataReader reader = myCommand.ExecuteReader())
{
// iterate your results here
}
}
Well spotted by other posters, I never caught the reserved word thing with your table name. I've amended my answer - but can't take credit for missing the obvious!
you should wrap user with brackets []
string strSQL = string.Format("Select * From [User] where UserId = '{0}'",user);
The query above is vulnerable to SQL Injection. It should be parameterized to avoid this. The following is an example:
string user = "1234";
string strSQL = "Select * From [User] where UserId = #userID";
SqlCommand myCommand = new SqlCommand(strSQL, cnn);
myCommand.AddWithValue("#userID", user);
reader = myCommand.ExecuteReader();
use the following
Try-Catch block for proper catching of errors
using statement for proper object disposal
snippet:
string user = "1234";
string strSQL = "Select * From [User] where UserId = #userID";
using (SqlConnection cnn = new SqlConnection("connection string here"))
{
using (SqlCommand myCommand = new SqlCommand(strSQL, cnn))
{
myCommand.Parameters.AddWithValue("#userID", user);
using (SqlDataReader reader = myCommand.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader["columnName"].ToString());
}
}
}
}
Wrap with []. It is a keyword. Read Reserved Keywords article from MSDN.
string strSQL = string.Format("Select * From [User] where UserId = '{0}'",user);
But more important part, your query is open for an SQL Injection attack. You should always use parameterized queries.
string strSQL = "Select * From [User] where UserId = #userID";
SqlCommand myCommand = new SqlCommand(strSQL, cnn);
myCommand.Parameters.AddWithValue("#userID", user);

Sql insert or update

I need to rapidly write code to insert/update SQL data. In classic ASP/VBScript I could do that like below:
Set rs = Server.CreateObject("adodb.Recordset")
sql = "SELECT * FROM _table WHERE id=" & id
rs.Open sql, cn, 1, 3
If rs.recordcount = 0 Then
rs.AddNew
End If
rs("data") = data
rs.Update
rs.Close
What could be the nearest C# port of this code snippet? Thanks!
Assuming MS-SQL:
using (SqlConnection conn = new SqlConnection("Connection String"))
using (SqlCommand comm = new SqlCommand("INSERT INTO MyTable (Name, Age) VALUES (#name, #age)", conn))
{
conn.Open();
comm.Parameters.AddWithValue("#name", "Adam");
comm.Parameters.AddWithValue("#age", 25);
comm.ExecuteNonQuery();
}
Connection string obviously needs fleshing out, and the parameterised SQL needs confirming, but this is the start of what you need.
You don't need to worry about closing as the using statement does this for you.
Update: not knowing classic ASP very well, I should clarify that this code only does an insert and not an update, if you need to do an update, change the SQL to use the update syntax.
Hopefully this gets you started. Make a reference to the ADODB class:
ADODB.Connection cn = new ADODB.Connection();
cn.Open("Provider=etc...", null, null, 0);
ADODB.Recordset rs = new ADODB.Recordset();
String sql = "SELECT * FROM _table WHERE id=" & id;
rs.Open(sql, cn, ADODB.CursorTypeEnum.adOpenKeyset, ADODB.LockTypeEnum.adLockOptimistic, -1);
if (rs.RecordCount == 0)
rs.AddNew;
rs("data") = data;
rs.Update();
rs.Close();
cn.Close();

error 'there is already an open datareader associated with this command which must be closed first'

runtime error 'there is already an open datareader associated with this command which must be closed first'
objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn);
objDataReader = objCommand.ExecuteReader();
while (objDataReader.Read())
{
objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + objDataReader[0] + "')", objConn);
objInsertCommand.ExecuteNonQuery();//Here is the error
}
objDataReader.Close();
I cannot define any stored procedure here.
Any help would we appreciated.
No need to do all that, just turn on MARS and your problem will get solved. In your connection string just add MultipleActiveResultSets=True;
You can't perform an action on that connection while it's still working on reading the contents of a data reader - the error is pretty descriptive.
Your alternatives are:
1) Retrieve all your data first, either with a DataSet or use the reader to populate some other collection, then run them all at once after the initial select is done.
2) Use a different connection for your insert statements.
How about pulling the data into a DataSet via Fill and then iterate through that to perform your insert via NonQuery?
IDbDataAdapter da;
IDbCommand selectCommand = connection.CreateCommand();
selectCommand.CommandType = CommandType.Text;
selectCommand.CommandText = "SELECT field1, field2 FROM sourcetable";
connection.Open();
DataSet selectResults= new DataSet();
da.Fill(selectResults); // get dataset
selectCommand.Dispose();
IDbCommand insertCommand;
foreach(DataRow row in selectResults.Tables[0].Rows)
{
insertCommand = connection.CreateCommand();
insertCommand.CommandType = CommandType.Text;
insertCommand.CommandText = "INSERT INTO tablename (field1, field2) VALUES (3, '" + row["columnName"].ToString() + "'";
}
insertCommand.Dispose();
connection.Close();
Your best bet would be to read the information you need into a list and then iterating the list to perform your inserts like so:
List<String> values = new List<String>();
using(SqlCommand objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn)) {
using(SqlDataReader objDataReader = objCommand.ExecuteReader()) {
while(objDataReader.Read()) {
values.Add(objDataReader[0].ToString());
}
}
}
foreach(String value in values) {
using(SqlCommand objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + value + "')", objConn)) {
objInsertCommand.ExecuteNonQuery();
}
}
INSERT INTO tablename (field1, field2)
SELECT 3, field1 FROM sourcetable
A single SQL statement instead of one per insert. Not sure if this will work for your real-life problem, but for the example you provided, this is a much better query than doing them one at a time.
On a side note, make sure your code uses parameterized queries instead of accepting strings as-is inside the SQL statement - your sample is open to SQL injection.
Several suggestions have been given which work great, along with recommendations for improving the implementation. I hit the MARS limit due to existing code not cleaning up a reader so I wanted to put together a more respectable sample:
const string connectionString = #"server=.\sqlexpress;database=adventureworkslt;integrated security=true";
const bool useMARS = false;
using (var objConn = new System.Data.SqlClient.SqlConnection(connectionString + (useMARS ? ";MultipleActiveResultSets=True" : String.Empty)))
using (var objInsertConn = useMARS ? null : new System.Data.SqlClient.SqlConnection(connectionString))
{
objConn.Open();
if (objInsertConn != null)
{
objInsertConn.Open();
}
using (var testCmd = new System.Data.SqlClient.SqlCommand())
{
testCmd.Connection = objConn;
testCmd.CommandText = #"if not exists(select 1 from information_schema.tables where table_name = 'sourcetable')
begin
create table sourcetable (field1 int, field2 varchar(5))
insert into sourcetable values (1, 'one')
create table tablename (field1 int, field2 varchar(5))
end";
testCmd.ExecuteNonQuery();
}
using (var objCommand = new System.Data.SqlClient.SqlCommand("SELECT field1, field2 FROM sourcetable", objConn))
using (var objDataReader = objCommand.ExecuteReader())
using (var objInsertCommand = new System.Data.SqlClient.SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, #field2)", objInsertConn ?? objConn))
{
objInsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("field2", String.Empty));
while (objDataReader.Read())
{
objInsertCommand.Parameters[0].Value = objDataReader[0];
objInsertCommand.ExecuteNonQuery();
}
}
}
Option 1:
Must execute query and load data before running another query.
Option 2:
Add MultipleActiveResultSets=true to the provider part of your connection string. See the example below:
<add name="DbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
What version of SQL Server are you using? The problem might be with this:
(from http://msdn.microsoft.com/en-us/library/9kcbe65k.aspx)
When you use versions of SQL Server before SQL Server 2005, while the SqlDataReader is being used, the associated SqlConnection is busy serving the SqlDataReader. While in this state, no other operations can be performed on the SqlConnection other than closing it. This is the case until the Close method of the SqlDataReader is called.
So, if this is what's causing your problem, you should first read all the data, then close the SqlDataReader, and only after that execute your inserts.
Something like:
objCommand = new SqlCommand("SELECT field1, field2 FROM sourcetable", objConn);
objDataReader = objCommand.ExecuteReader();
List<object> values = new List<object>();
while (objDataReader.Read())
{
values.Add(objDataReader[0]);
}
objDataReader.Close();
foreach (object value in values)
{
objInsertCommand = new SqlCommand("INSERT INTO tablename (field1, field2) VALUES (3, '" + value + "')", objConn);
objInsertCommand.ExecuteNonQuery();
}
Adding this to connection string should fix the problem.
MultipleActiveResultSets=true
Try something like this:
//Add a second connection based on the first one
SqlConnection objConn2= new SqlConnection(objConn.connectionString))
SqlCommand objInsertCommand= new SqlCommand();
objInsertCommand.CommandType = CommandType.Text;
objInsertCommand.Connection = objConn2;
while (objDataReader.Read())
{
objInsertCommand.CommandText = "INSERT INTO tablename (field1, field2) VALUES (3, '" + objDataReader[0] + "')";
objInsertCommand.ExecuteNonQuery();
}
Best Solution:
There is only problem with your "CommandText" value. Let it be SP or normal Sql Query.
Check 1: The parameter value which you are passing in your Sql Query
is not changing and going same again and again in your ExecuteReader.
Check 2: Sql Query string is wrongly formed.
Check 3: Please create simplest code as follows.
string ID = "C8CA7EE2";
string myQuery = "select * from ContactBase where contactid=" + "'" + ID + "'";
string connectionString = ConfigurationManager.ConnectionStrings["CRM_SQL_CONN_UAT"].ToString();
SqlConnection con = new SqlConnection(connectionString);
con.Open();
SqlCommand cmd = new SqlCommand(myQuery, con);
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
con.Close();
In order for it to be disposed easily i use the following coding-template :
`using (SqlConnection connection = new SqlConnection("your connection string"))
{
connection.Open();
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "Select * from SomeTable";
using (SqlDataReader reader = cmd.ExecuteReader())
{
if(reader.HasRows)
{
while(reader.Read()){
// assuming that we've a 1-column(Id) table
int id = int.Parse(reader[0].ToString());
}
}
}
}
connection.Close()
}`

Categories