Using C# to connect and insert to SQL Server 2012 - c#

I'm working on some code to try and get my array that's entered by the user to connect and send to SQL Server 2012. I've been told to use all of these commands to connect to the database.
One of my issues is that I've been looking through Stack Overflow and everyone suggests using parameters instead of concatenating to avoid SQL injection, but this is for my class and we are only 2 weeks into C# so I don't think he's going to like it if I use parameters.
I think my try catch is wrong, the top half is filled with red lines and how do you use the INSERT command with a for loop?
protected void btnDisplay_Click(object sender, EventArgs e)
{
//try
//{
// System.Data.SqlClient.SqlConnection varname1 = new System.Data.SqlClient.SqlConnection();
// varname1 = "server = LOCALHOST"; Database = Lab1; Trusted_connection = yes;
// varname1.Open();
// System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
// cmd.Connection = conn;
// cmd.CommandText = "Delete From Student";
// cmd.ExecuteNonQuery();
//
string sql = null;
for(int i=0; counter1 >= i; i++)
{
sql += "INSERT into Student VALUES(" + StudentId + Name + Address);
}
varname1.Close();
//}
catch (SqlException ex)
{
MessageBox.Show("Database failed" + ex.Message);
}
}

So, there are quite a few problems with this code. It might be best to spend another hour on it or so, then post any specific questions you can't figure out. Let me give you a few quick pointers though.
You have a catch() block, but the matching try block is commented out. This will result in a compiler error. It looks like you were just debugging some stuff, so no big deal. However, it's usually wise to post the actual code you're trying to run.
You're initializing a string to null, but you're concatenating on to the end. This will result in a runtime error. You should initialize your string to String.Empty instead. Also, look into the StringBuilder class if you're doing large amounts of string concatenation, as it's much faster.
You're (in theory) building a SQL string, but never actually running it anywhere. Nor do you return the value to anything that could run it.
Your INSERT statement isn't even valid. You don't have a matching end ) in the INSERT statement, and you have a rogue ) after your variables, which will result in a compiler error. You also just mash all the variables together, without quotes or commas between them. You probably want something more like:
sql += String.Format("INSERT into Student VALUES('{0}', '{1}', '{2}');", StudentId, Name, Address);
Use parameterized queries. Always. Who cares what your teacher says. If you don't, at the very least, check the strings for apostrophes first, as these will screw up your SQL statement by prematurely ending the string.
Your loop doesn't seem to make much sense. What is counter1? What value does it have? Even if it's set to a positive value, all you're doing is building the same SQL string over and over again since the values within the loop don't change. It's not clear what you're trying to do here.
You're calling varname1.Close(); but you've commented out the declaration of varname1, which will result in a compiler error.
Hope this helps!

Is this what you are after. You may have to adapt some of it. Sorry if it doesent fully work dont have a debugger at the moment.
class Data {
public int StudentId {get;set;}
public string Name {get;set;}
public string Address {get;set;}
}
protected void btnDisplay_Click(object sender, EventArgs e)
{
var datas = new List<Data>();
try
{
StringBuilder sql = new StringBuilder();
foreach(data in datas)
{
sql.Append(String.Format("INSERT into Student VALUES({0},'{1}','{2}') ",data.UserId,data.Name,data.Address));
}
var sqlConnection = new SqlConnection(#"Data Source=LOCALHOST;Initial Catalog=Lab1;Trusted_Connection=True;");
sqlConnection.Open();
var command = new SqlCommand(sql.ToString(),sqlConnection);
command..ExecuteNonQuery();
sqlConnection.Close();
}
catch(SqlException ex){
MessageBox.Show("Database failed" + ex.Message);
}
}

Related

How to fix 'SQLite exception, Insufficient parameters supplied to the command' when using INSERT statement

I'm attempting to insert data from an object into my sqlite database table. I keep on receiving the same error when attempting to do so.
When inserting data into a different table (words) of the same db, using the same technique, I am able to successfully insert the data without errors. This leads me to believe that my SQLiteConnection value 'cnn' is not the issue. I have ensured that the names of the object properties are the same, as well as the fields within the table. There is no primary key within this specific table, but I'm not sure if that's a problem or not.
The code that doesnt work:
using (IDbConnection cnn = new SQLiteConnection(connection))
{
foreach (bridgeRecord br in bridgeWords)
{
try
{
cnn.Execute("insert into bridge (engWord, spaWord, frequency, wordClass) values (#engWord, #spaWord, #frequency, #wordClass)", br);
}
catch (SQLiteException ex)
{
Console.WriteLine(ex);
}
}
}
The code that does work:
using (IDbConnection cnn = new SQLiteConnection(connection))
{
foreach (Word w in words)
{
try
{
cnn.Execute("insert into words (word, wordSimplified, confidence, difficulty, wordClass, wordCategory, dateTestedLast, popularity, language) " +
"values (#word, #wordSimplified, #confidence, #difficulty, #wordClass, #wordCategory, #dateTestedLast, #popularity, #language)", w);
}
catch (SQLiteException ex)
{
wordsBouncedBack.Add(w.word);
continue;
}
}
}
The 'bridgeRecord' class model looks like this:
class bridgeRecord
{
public string engWord;
public string spaWord;
public int frequency;
public string wordClass;
}
This is the error i receive:
code = Unknown (-1), message = System.Data.SQLite.SQLiteException (0x80004005): unknown error
Insufficient parameters supplied to the command
at System.Data.SQLite.SQLiteStatement.BindParameter(Int32 index, SQLiteParameter param)
I expected the 'bridgeRecord' object to provide the parameters to be inserted but this is not the case. Although the 'Word' object seems to provide the parameters just fine which confuses me greatly.
Any help would be very much appreciated. This is my first stack overflow question so I'm sorry if the answer is extremely obvious :)
Taking the advice of Pascal in the comments, I used the command.parameters.add method to fix my issue. I prepared the statment before-hand and then added the parameters into their correct place. The final code now looks like this:
SQLiteCommand command = new SQLiteCommand("insert into bridge (id, engWord, spaWord, frequency, wordClass) values (#id, #engWord, #spaWord, #frequency, #wordClass)",cnn);
command.Parameters.AddWithValue("#id", br.engWord + br.spaWord + br.frequency + br.wordClass);
command.Parameters.AddWithValue("#engWord", br.engWord);
command.Parameters.AddWithValue("#spaWord", br.spaWord);
command.Parameters.AddWithValue("#frequency", br.frequency);
command.Parameters.AddWithValue("#wordClass", br.wordClass);
command.ExecuteNonQuery();
It would of been better to find a fix which enabled the code to work like the other INSERT statement, but this work around will suffice.
Sometimes you can get this error when one of your values has a single quote:
St. John's

Check the duplicate entering

I using this code to entering .
private void button1_Click(object sender, EventArgs e)
{
string Coonstring = "datasource=localhost;port=3306;username=root;password=****;Charset=utf8";
string cmd = "Insert into project.name_registry (name ) values('" + this.txt.Text + "');";
MySqlConnection connectionDatabase = new MySqlConnection(Coonstring);
MySqlCommand cmddata = new MySqlCommand(cmd, connectionDatabase);
MySqlDataReader myreader;
try
{
connectionDatabase.Open();
myreader = cmddata.ExecuteReader();
MessageBox.Show("Done");
while (myreader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I need when press on this button check if the insert name found messagebox appear tell my the name exists and prevent the add. If not tell me the insert Done. How i can do this.
Regards
The best place to have this sort of check is in the database itself. Almost all databases can set a UNIQUE constraint on a field. If you set the name column in the name_registry to be unique, the DBMS won't let you add a second entry with the same name, and an exception will be thrown. This will usually be the best way.
If the DB isn't in your hands and you can't set the column to be unique, you can use the suggestion that #FrancisDucharme and others and query the DB for the given name, and only call the INSERT if it returns 0 results:
SELECT COUNT(*) FROM name_registry WHERE [name] = 'TheName'
Note, though that there's no need to call ExecuteReader, not for this single-result SELECT statement, nor for the INSERT statement above - you should call ExecuteScalar, which will return the single-value result without loading a full-scale DataReader that you don't really need.
And lastly, as an addition to the answer, I can't in good conscience let you go on without pointing you in the direction of at least one tutorial about using parameterized queries in ADO.NET, which not only help prevent SQL injection attacks, but also help clean up the code and make it more readable, in my opinion. There are many out there.
Firstly, As previously stated: You have MAJOR SQL Injections visible...
Secondly, You should be using params.
Third, If you
SELECT *
FROM [TABLE]
WHERE [ColumnName] = #Param

Creating Registration form in c# with mysql

Hello so i m creating a registration form in C# with MySql so it connects to the database and everything but i get this error Napaka pri registraciji Unknown column " in 'field list' the translation of Napaka pri registraciji means Error at registering i just have it in my language. I get this error when i insert data in textboxes and press Register..
the code:
private void btn_Reg_Click(object sender, EventArgs e)
{
MySqlConnection dataConnection = new MySqlConnection();
dataConnection.ConnectionString = "datasource=localhost;port=3306;username=root;password=";
dataConnection.Open();
MySqlTransaction transakcija = dataConnection.BeginTransaction();
MySqlCommand dataCommand = new MySqlCommand();
dataCommand.Connection = dataConnection;
dataCommand.Transaction = transakcija;
try
{
dataCommand.CommandText = "Insert INTO lr.users (upIme,geslo) VALUES (`"+this.tB_upIme.Text+"`,`"+this.tB_geslo.Text+"`)";
dataCommand.CommandType = CommandType.Text;
dataCommand.ExecuteNonQuery();
transakcija.Commit();
MessageBox.Show("Registracija uspešna!");
}
catch (Exception eks)
{
transakcija.Rollback();
MessageBox.Show("Napaka pri registraciji\n" + eks.Message);
}
finally
{
dataCommand.Connection.Close();
}
}
There are two things I immediately see wrong here...
First, you're using back ticks to wrap your values. In MySQL Back ticks represent database objects, so the query is looking for objects named by those values instead of using the values themselves. So instead of this:
`"+this.tB_upIme.Text+"`
You'd want this:
'"+this.tB_upIme.Text+"'
Second, and vastly more importantly, your code is wide open to SQL injection attacks. You'll want to use query parameters, not direct string concatenation. While it may look like you're just putting values into the query string, you're actually taking user input and treating it as executable code in your query string, which means users can run any arbitrary code they want on your database.
First, add parameters to your query:
"Insert INTO lr.users (upIme,geslo) VALUES (#upIme, #geslo)"
(You'll notice this also makes the query a heck of a lot cleaner and easier to read.) Then add your parameters to the command:
dataCommand.Parameters.AddWithValue("#upIme", this.tB_upIme.Text);
dataCommand.Parameters.AddWithValue("#geslo", this.tB_geslo.Text);
Then when you execute that command it will treat the user-input values as values instead of as executable code.
Change to single quotes ' in the values.
dataCommand.CommandText =
"Insert INTO lr.users (upIme,geslo)
VALUES ('"+this.tB_upIme.Text+"','"+this.tB_geslo.Text+"');";

Add Unique Column Name to Access Database via Application - C#

I have a program which records ID,Name,TimeIn,TimeOut. On the first scan of a card it record the id,name and timein, and then on second swipe it adds to the timeout column. I am trying to get it to add another "TimeIn" column on the third swipe, so I tried to get it to insert "TimeIn + Unique Number", but it does not pick up the variable due to the quotes.
Here is my code:
private void SignIn_Time(OleDbCommand updateCmd, OleDbConnection OLEDB_Connection, Object varName, Object varID, String varTime)
{
object varTimeColumn;
varTimeColumn = "TimeIn" + GetUniqueNumber();
updateCmd.CommandText = "ALTER TABLE TestDB ADD COLUMN varTimeColumn TEXT";
updateCmd.CommandText = "INSERT INTO TestDB (varTimeColumn) VALUES (#TIMEIN)";
updateCmd.Parameters.AddWithValue("#TIMEIN", varTime);
OLEDB_Connection.Open();
updateCmd.Connection = OLEDB_Connection;
updateCmd.ExecuteNonQuery();
OLEDB_Connection.Close();
}
static int counter;
public static int GetUniqueNumber()
{
return counter++;
}
There are two errors in the code above:
The Access Jet Engine doesn't support two concatenated commands. You should send each command by itself.
Another problem is the variable name used to represent the column name. You cannot embedd the variable inside the command. You should put its value, and to do that, you could only use a string concatenation.
private void SignIn_Time(OleDbCommand updateCmd, OleDbConnection OLEDB_Connection,
Object varName, Object varID, String varTime)
{
try
{
OLEDB_Connection.Open();
string varTimeColumn = "TimeIn" + GetUniqueNumber().ToString();
updateCmd.Connection = OLEDB_Connection;
updateCmd.CommandText = "ALTER TABLE TestDB ADD COLUMN " + varTimeColumn + " TEXT";
updateCmd.ExecuteNonQuery();
updateCmd.CommandText = "INSERT INTO TestDB (varTimeColumn) VALUES (#TIMEIN)";
updateCmd.Parameters.AddWithValue("#TIMEIN", varTime);
updateCmd.ExecuteNonQuery();
OLEDB_Connection.Close();
}
catch(Exception ex)
{
if(OLEDB_Connection.State == ConnectionState.Open)
OLEDB_Connection.Close();
// Perhaps in debug you could do something here with the exception like a log message
// or rethrow the execption to be handled at an upper level...
throw;
}
}
static int counter;
public static int GetUniqueNumber()
{
return counter++;
}
Also I suggest to use a try/catch block around your code because, in case of exceptions, you don't close the connection. A better approach should be the using statement, but from the code above is not clear how to implement this pattern
I completely agree with the comment from #Corak above. The proposed solution is the only rationale approach to your logical requirements. Also, remember that an Access Table has limitations on the max number of columns that could be added to a table. 255 is this limit and your code doesn't seem to keep this in any consideration.
Microsoft Access 2010 specifications

How to get multiple rows from stored procedure?

I have a method for adding values to the database for all operations.
If this is selected from the database and this select return more rows from the database,
how can I get the rows and store in an array?
This is the method code :
public void ExcuteProcedure(string procName, List<SqlParameter> procparams)
{
try
{
SqlConnection mycon = new SqlConnection(connectionString);
mycon.Open();
SqlCommand mycom = new SqlCommand();
mycom.Connection = mycon;
mycom.CommandText = procName;
mycom.CommandType = CommandType.StoredProcedure;
foreach (var item in procparams)
{
SqlParameter myparm = new SqlParameter();
myparm.ParameterName = item.ParameterName;
// myparm.SqlDbType = item.SqlDbType;
myparm.Value = item.Value;
mycom.Parameters.Add(myparm);
}
var n= mycom.ExecuteScalar();
mycon.Close();
}
catch (SqlException e)
{
Console.WriteLine("Error Number is : " + e.Number);
Console.WriteLine("Error Message is : " + e.Message);
}
}
You need to call mycom.ExecuteReader(), which will give you a SqlDataReader which can read through the results.
Call Read() to advance through the rows.
It never ceases to amaze me the number of times I see devs trying to abstract away simple database connectivity; and the myriad of ways they inevitably screw it up.
The following may sound mean, but it needs said:
Clean up your code, it leaks like a sieve. Using clauses around the connection and command objects are pretty much mandatory. As it stands if you forget a single parameter or put in a bad value you will leak connections. Once the connection pool is filled up your app will crash in all sorts of interesting, and usually hard to debug, ways.
Next, if you aren't sure how to properly get records back from a database then you probably shouldn't try to abstract the code calling your procedures. Either use a lightweight ORM like Dapper or learn how what you are doing will ultimately involve a lot of extraneous code that the next developer on your project will want to rip out.
/rant over.
Getting back to the question: ExecuteScalar returns a single value. You need to use ExecuteReader. I'd suggest that you simply take the results of the reader, stuff it into a datatable and pass that back to the calling code.
var n = mycom.ExecuteScalar();
Scalar: an atomic quantity that can hold only one value at a time
Return a DataReader instead, and iterate through its rows
Fill a DataSet by using a DataAdapter (this is more appropriate if you have multiple tables in the result set).

Categories