please help. in Visual Studio 2017 and SQL localDB - WinForm learns and makes a small application. Form (Textbox), where "name, surname, address, city, phone and email" is written in Czech language containing "ěščřžýáíé" ". Everything is stored in the database (nvarchar) in order. Everything OK.
In Form2 I have another form where Combobox calls a "surname" and it has to fill in the phone and e-mail automatically from the database. If the surname is without the character "ěščřžýáíé", everything will be displayed correctly. If it contains "ěščřžýáíé", only the last name will be displayed, but the phone and email will not be loaded into the TextBox.
The code sample (without ěščřžýáíé) works perfectly:
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\newtest.mdf;Integrated Security=True");
string sql = "select * from test111 WHERE firmadat ='" + prijmeniComboBox.Text + "'; ";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataReader myreader;
try
{
con.Open();
myreader = cmd.ExecuteReader();
while (myreader.Read())
{
string rollno = myreader.GetInt32(0).ToString();
string name = myreader.GetString(1);
string telephone = myreader.GetString(3);
string email = myreader.GetString(4);
textBox1.Text = rollno;
telefonTextBox.Text = telephone;
emailTextBox.Text = email;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Thank you for your help.
The problem is probably here:
string sql = "select * from test111 WHERE firmadat ='" + prijmeniComboBox.Text + "'; ";
Here you take your Unicode string and you concatenate it into a SQL string that is not a Unicode string. I would tell you how to get it working as you intended but this is a really really dangerous way to write SQLs. Someone at kids' toy maker VTech wrote SQLs this way and enabled a hacker to download millions of images of children taken by vtech devices. If one of my developers wrote SQL like this they would be subject to disciplinary action, possibly being fired.
I strongly recommend that you use parameterized SQLs; any number of internet resources will show you how, such as http://bobby-tables.com - it will also solve the problem of getting no results when searching using a search term that contains non-ASCII characters
Take a look at http://dapper-tutorial.net ; using dapper will not only take care of the parameterizing for you, but make your database life easier by reducing your code to just a couple of lines, something like:
using(SqlCommand x = new SqlCommand(conn)
{
var p = x.Query(
"select * from test111 WHERE firmadat = #a",
new { a = prijmeniComboBox.Text }
);
firstNameTextBox.Text = p.FirstName; //or what the column is called on db
...
}
You just write your sql, use #namedParameter placeholders and supply an anonymous object with properties named after the placeholders. Dapper does the rest. If you have a Person class in your project you can even get dapper to create it and populate it for you
Related
I try to UPDATE data in my SQL Server database and I get this error:
System.Data.SqlClient.SqlException
Incorrect syntax near 'de'
Unclosed quotation mark after the character string ')'
private void BtEnrMod_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=.\\BD4X4;Initial Catalog=BD4X4;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand("UPDATE Service SET Type = " + TxBxService.Text + ", Prix = " + TxBxPrix.Text + "WHERE Code = " + LbCodeAff.Text + "')", con);
int i = cmd.ExecuteNonQuery();
if (i != 0)
{
MessageBox.Show("Service Modifié");
}
else
{
MessageBox.Show("Erreur");
}
this.Close();
con.Close();
}
Replace the one liner that declares your command with this code block:
SqlCommand cmd = new SqlCommand("UPDATE Service SET Type = #t, Prix = #p WHERE Code = #c", con);
cmd.Parameters.AddWithValue("#t", TxBxService.Text);
cmd.Parameters.AddWithValue("#p", TxBxPrix.Text);
cmd.Parameters.AddWithValue("#t", LbCodeAff.Text);
Always avoid writing an sql where you string concatenate in a value provided by the user in a text box; it's the number one security horror you can make with sql. Always use parameters to put values in, like you see here. For more info on this SQL injection hacking, see http://bobby-tables.com
If you ever fin yourself in a situation where you think you have to concatenate to make an sql, don't concatenate a value in; concatenate a parameter in and add the value into the parameters collection. Here's a hypothetical example:
var cmd = new SqlCommand("","connstr");
strSql = "SELECT * FROM table WHERE col IN (";
string[] vals = new[]{ "a", "b", "c" };
for(int x = 0; x<vals.Length; x++){
strSql += ("#p"+x+",");
cmd.Parameters.AddWithValue("#p"+x, vals[x]);
}
cmd.CommandText = strSql + ")";
This uses concatenation to make an sql of SELECT * FROM table WHERE col IN (#p0, #p1, #p2) and a nicely populated parameters collection
When you're done grokking that, read the link Larnu posted in the comments. There are good reasons to avoid using AddWithValue in various scenarios but it will always be preferable to concatenation of values. Never ditch the use of parameters "because I read a blog one time about how AddWithValue is bad" - form parameters using the new parameter constructor, or use AddWithValue shortcut, but never concat values
Or better still than all of this, use an ORM like Entity Framework, nHibernate or Dapper and leave most of this boring boilerplate low level SQL drudgery behind. These libraries do most of this wrangling for you; EF and nH even write th sql too, dapper you write it yourself but it takes care of everything else
Using a good ORM is like the difference between writing creating a UI manually line by line of position, font, anchor, event code for every button, label and text box versus using the windows forms designer; a world apart and there's no sense in taking hours to create manually what software can do more comprehensively, faster and safer for you in seconds
First post here so, first of all, thanks for the existence of this site since it has helped me lots so far.
Right now I'm making a project (C#) that requires a user to login. The profiles are stored on an SQL base and I need to check if the credentials (user/pass) are correct to allow the login.
I understand very little of SQL, so bare with my errors, please.
The form is working quite nicely. What doesn't work is the data check on my database. So, when I press login the form calls the following function:
public bool ValidacaoLogin(string user, string pass)
cn.Open();
cmd = new SqlCommand("select * from BDPerfil left join BDPerfilTecnico on BDPerfil.USER = BDPerfilTecnico.USER where BDPerfil.USER = #USER;", cn);
cmd = new SqlCommand("select * from BDPerfil where NIF = '" + user + "' AND PASSWORD = '" + pass + "';", cn);
cmd.Parameters.AddWithValue("#USER", user);
cmd.Parameters.AddWithValue("#PASSWORD", pass);
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
if ("#USER" == user)
{
if ("#PASSWORD" == pass)
dr.Close();
cn.Close();
return true;
}
}
}
dr.Close();
cn.Close();
return false;
}
I have 2 tables to store different profiles: BDPerfilTecnico and BDPerfilAssist so I want my program to check both (through join) although right now I don't need to use BDPerfilAssist since all my test profiles are on BDPerfilTecnico.
Help?
Thanks in advance.
At the very least, you need the parameters in the query. I would expectd:
cmd = new SqlCommand("select * from BDPerfil where NIF = #USER AND PASSWORD = #PASSWORD'", cn);
You are onto a good path using parameters for the queries. You just need them in the query itself.
Note: There may be other issues in the code as well.
The results back will be in the dr variable and will depend on what the columns are in the table. Instead of * you should probably list the table columns that you want i.e. User,password. Then you can use the dr variable to get these values with statements like dr.getString(0) to get user and dr.getString(1) for password. The variables user and password will not get changed by the query in your code. Also the literal strings "#user" and "#password" won't come out of the query so I don't know why you would compare to them. Instead you want to do something like. If (dr.getString(0)==user)
Please please encrypt the password in the database. You can encrypt what the user types and compare encrypted password to encrypted password.
Good luck
I am trying to do create a where clause to pass as a parameter to an Oracle command and it's proving to be more difficult than I thought. What I want to do is create a big where query based off user input from our application. That where query is to be the single parameter for the statement and will have multiple AND, OR conditions in it. This code here works however isn't exactly what I require:
string conStr = "User Id=testschema;Password=pass12341;Data Source=orapdex01";
Console.WriteLine("About to connect to Database with Connection String: " + conStr);
OracleConnection con = new OracleConnection(conStr);
con.Open();
Console.WriteLine("Connected to the Database..." + Environment.NewLine + "Press enter to continue");
Console.ReadLine();
// Assume the connection is correct because it works already without the parameterization
String block = "SELECT * FROM TEMP_VIEW WHERE NAME = :1";
// set command to create anonymous PL/SQL block
OracleCommand cmd = new OracleCommand();
cmd.CommandText = block;
cmd.Connection = con;
// since execurting anonymous pl/sql blcok, setting the command type
// as text instead of stored procedure
cmd.CommandType = CommandType.Text;
// Setting Oracle Parameter
// Bind the parameter as OracleDBType.Varchar2
OracleParameter param = cmd.Parameters.Add("whereTxt", OracleDbType.Varchar2);
param.Direction = ParameterDirection.Input;
param.Value = "MY VALUE";
// Get returned values from select statement
OracleDataReader dr = cmd.ExecuteReader();
// Read the identifier for each result and display it
while (dr.Read())
{
Console.WriteLine(dr.GetValue(0));
}
Console.WriteLine("Selected successfully !");
Console.WriteLine("");
Console.WriteLine("***********************************************************");
Console.ReadKey();
If I change the lines below to be the type of result I want then I get an error "ORA-00933: SQL command not properly ended":
String block = "SELECT * FROM TEMP_VIEW :1";
...
...
param.Value = "WHERE NAME = 'MY VALUE' AND ID = 5929";
My question is how do I accomplish adding my big where query dynamically without causing this error?
Sadly there is no easy way to achieve this.
One thing you will need to understand with parameterised SQL in general is that bind parameters can only be used for values, such as strings, numbers or dates. You cannot put bits of SQL in them, such as column names or WHERE clauses.
Once the database has the SQL text, it will attempt to parse it and figure out whether it is valid, and it will do this without taking any look at the bind parameter values. It won't be able to execute the SQL without all of the values.
The SQL string SELECT * FROM TEMP_VIEW :1 can never be valid, as Oracle isn't expecting a value to immediately follow FROM TEMP_VIEW.
You will need to build up your SQL as a string and also build up the list of bind parameters at the same time. If you find that you need to add a condition on the column NAME, you add WHERE NAME = :1 to the SQL string and a parameter with name :1 and the value you wish to add. If you have a second condition to add, you append AND ID = :2 to the SQL string and a parameter with name :2.
Hopefully the following code should explain a little better:
// Initialise SQL string and parameter list.
String sql = "SELECT * FROM DUAL";
var oracleParams = new List<OracleParameter>();
// Build up SQL string and list of parameters.
// (There's only one in this somewhat simplistic example. If you have
// more than one parameter, it might be easier to start the query with
// "SELECT ... FROM some_table WHERE 1=1" and then append
// " AND some_column = :1" or similar. Don't forget to add spaces!)
sql += " WHERE DUMMY = :1";
oracleParams.Add(new OracleParameter(":1", OracleDbType.Varchar2, "X", ParameterDirection.Input));
using (var connection = new OracleConnection() { ConnectionString = "..."})
{
connection.Open();
// Create the command, setting the SQL text and the parameters.
var command = new OracleCommand(sql, connection);
command.Parameters.AddRange(oracleParams.ToArray());
using (OracleDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// Do stuff with the data read...
}
}
}
Hello everyone i am creating a settings page for another application using mvc4. In the settings page:
1.It contains two text areas wherein the user can type anything.
2.After typing if the user clicks submit button, the text he has written is saved in a sql database.
3.The main application will read that data from the database and display it.
Here are my respective codes:
Model:
public string PartnerInfo1 { get; set; }
public string PartnerInfo2 { get; set; }
Controller:
[HttpPost]
public ActionResult Index(AddDetailModel model)
{
pinfo1 = model.PartnerInfo1;
pinfo2 = model.PartnerInfo2;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Sample"].ConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("update dbo.Partner_Design set PartnerInfo1='" + pinfo1 + "',PartnerInfo2='" + pinfo2 + "' where [PartnerID]='cs'", con);
cmd.ExecuteNonQuery();
return RedirectToAction("Index");
}
and in the view:
#Html.TextAreaFor(m => m.PartnerInfo1)
#Html.TextAreaFor(m => m.PartnerInfo2)
in the database, the corresponding table contains two columns PartnerInfo1,PartnerInfo2 and their datatype is nvarchar(max).
My problem is when i type apostrophe in text area it gives me error.For example if i type "world's" it gives error on clicking submit button.
This is the error:
Incorrect syntax near 's'.
Unclosed quotation mark after the character string ''.
Please suggest what i can do to avoid this.Any help would be appreciated.
Never do that - it's unsafe and allow to make sql injection:
SqlCommand cmd = new SqlCommand("update dbo.Partner_Design set PartnerInfo1='" + pinfo1 + "',PartnerInfo2='" + pinfo2 + "' where [PartnerID]='cs'", con);
Instead of that use the following parameters syntax:
SqlCommand cmd = new SqlCommand("update dbo.Partner_Design set PartnerInfo1=#pinfo1, PartnerInfo2=#pinfo2 where [PartnerID]='cs'", con);
cmd.Parameters.AddWithValue("#pinfo1", pinfo1);
cmd.Parameters.AddWithValue("#pinfo2", pinfo2);
Your method expose your query to sql injection attacks. You are much better using a parameterised query which will sort out your ' issue as well.
string connString = ConfigurationManager.ConnectionStrings["Sample"].ConnectionString;
using (SqlConnection con = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand("Update dbo.Partner_Design " +
"Set PartnerInfo1=#pinfo1, " +
"PartnerInfo2=#pinfo2 " +
"Where [PartnerID]=#partnerId", con);
cmd.Parameters.AddWithValue("#pinfo1", model.PartnerInfo1);
cmd.Parameters.AddWithValue("#pinfo2", model.PartnerInfo2);
cmd.Parameters.AddWithValue("#partnerId", "cs");
con.Open();
cmd.ExecuteNonQuery();
}
You can escape the single quote by prefixing it with another single quote, which would require doing a replace on your string before you add it to the query i.e.:
pinfo1 = pinfo1.Replace("'", "''");
pinfo2 = pinfo2.Replace("'", "''");
SqlCommand cmd = new SqlCommand("update dbo.Partner_Design set PartnerInfo1='" + pinfo1 + "',PartnerInfo2='" + pinfo2 + "' where [PartnerID]='cs'", con);
I would however strongly advise against this and take the advice of the other responses that instead use parameterised SQL which is much more secure. Note also that this solution will only solve your single quotes problem, and will still cause issues with other special characters that need escaping individually. As such whilst this should answer your question, the solutions proposed by Sławomir Rosiek and Kaf are much more comprehensive, much safer, and are best practice.
The method you are using leaves you open to SQL injection attacks.
I need to know that i have 3 tables one with sessional marks with primary key sessional id and another table student with student id as primary key and third table Data with student id and sessional id as foreign keys.
Now i need to update marks of each student in grid view so that marks get stored in sessional marks table.
i am using this query
string hourly1;
string hourly2;
string student_id;
for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++)
{
hourly1 = dataGridView1[1,i].Value.ToString();
hourly2 = dataGridView1[2,i].Value.ToString();
student_id = Convert.ToString(dataGridView1[3, i].Value);
SqlCommand cmd = new SqlCommand("UPDATE SessionalMarks SET " +
"SessionalMarks.Hourly1Marks = '" + hourly1 + "'," + "SessionalMarks.Hourly2Marks = '" + hourly2 + "'from Student,DATA where Student.StudentId=DATA.StudentId AND Student.StudentId='" + student_id + "'", conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
but this query is adding same marks in each row in need to update marks which are placed in the grid view
i think there is a problem in where clause can some one help me please.
It's very unclear what your SQL schema looks like, but in your update statement, everything after FROM isn't being used for any purpose. Your WHERE clause doesn't mention SessionalMarks, so each time you loop through your for loop you're updating all rows in that table.
If you post your SQL schema of these three tables, it might help us understand the shape of your data and help you write a better query. The way you've described it, it sounds like the DATA table ought to contain the marks for each student, but you've apparently put that data in the SessionalMarks table instead.
However, your code has some problems besides the one you've mentioned:
You're composing a SQL query by joining strings together, and it looks like those strings might have come from the user. This exposes you to a SQL injection attack, or at least if the user types a ' your program will behave incorrectly.
You're opening and closing the database connection repeatedly, instead of opening it once and closing it when you're finished.
To fix these problems, you probably should (a) use a parameterized SQL query, and (b) open and close the database connection outside of the loop.
This isn't perfect, but it's a start:
// this query needs to be fixed
string query = #"UPDATE SessionalMarks
SET SessionalMarks.Hourly1Marks = #hourly1
,SessionalMarks.Hourly2Marks = #hourly2
FROM Student,DATA
WHERE Student.StudentId = DATA.StudentId
AND Student.StudentId = #studentid";
// Make sure we dispose of the SqlCommand when we're finished with it
using (SqlCommand cmd = new SqlCommand(query, conn))
{
// Create my three parameters, don't need a value yet
// Need to make sure we have the right SqlDbType specified
cmd.Parameters.Add( new SqlParameter("#hourly1", SqlDbType.Decimal) );
cmd.Parameters.Add( new SqlParameter("#hourly2", SqlDbType.Decimal) );
cmd.Parameters.Add( new SqlParameter("#studentid", SqlDbType.Int) );
conn.Open();
try
{
// For each row in our DataGridView
// We could also use foreach(DataGridViewRow row in dataGridView1.Rows)
for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++)
{
// Fill in our parameters with our values
cmd.Parameters[0].Value = dataGridView1[1,i].Value.ToString();
cmd.Parameters[1].Value = dataGridView1[2,i].Value.ToString();
cmd.Parameters[2].Value = Convert.ToString(dataGridView1[3, i].Value);
cmd.ExecuteNonQuery();
}
}
finally
{
// Close our database connection even if cmd.ExecuteNonQuery() throws
conn.Close();
}
}