code for Inserting into database
query = "INSERT INTO Question(Image, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer)"
+ $"VALUES(\""{name}\",\""{answerList[0]}\",\"{answerList[1]}\",\""{answerList[2]}\",\"{answerList[3]}\",\"{name}\"};";
I am getting error in this line as "; expected":
+ $"VALUES(\""{name}\",\""{answerList[0]}\",\"{answerList[1]}\",\""{answerList[2]}\",\"{answerList[3]}\",\"{name}\");";
In three places, you have an unescaped second double quote, which ends the quoted string right there:
\""{name
and
\""{answerList[0]
and
\""{answerList[2]
Those break your C#, and if you escaped them, they'd break your SQL. So don't do that. Almost certainly, you should be using single quotes rather than double quotes as well (thanks Icarus):
query = "INSERT INTO Question(Image, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer)"
+ $"VALUES('{name}','{answerList[0]}','{answerList[1]}','{answerList[2]}','{answerList[3]}','{name}'};";
However, that's very bad coding style. It's vulnerable to SQL injection attacks, it'll crash if one of your answers happens to have an apostrophe in it, and putting quoted or even just matched quotes in a string is highly error-prone, as you've discovered.
So start over and rewrite the code using parameters, which resolve all of these issues cleanly and simply:
SqlCommand cmd = new SqlCommand();
// ...etc.
cmd.Parameters.Add("#name", SqlDbType.NVarChar);
cmd.Parameters.Add("#answerList0", SqlDbType.NVarChar);
// ...etc.
cmd.Parameters["#name"].Value = name;
cmd.Parameters["#answerList0"].Value = answerList[0];
// ...etc.
query = "INSERT INTO Question(Image, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer)"
+ "VALUES(#name,#answerList0,#answerList1,#answerList2,#answerList3,#name};";
try to build the string using like this:
$#"query = ""INSERT INTO Question(Image, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer)""
""VALUES(""{name}"",""{ answerList[0]}"",""{answerList[1]}"",\""{
answerList[2]}"",""{answerList[3]}"",""{name}""};"";";
never use a + when building strings, because it will evaluate both and then append them to a third instead of creating just 1 string.
Related
I have the following query -
string query = "Insert into table(userId,companyID) values(" + userId + "," + SplitedLine[1] + ")";
writer.WriteLine(query);
When I am printing running this code then it is not printing the entire query in one column, rather it is breaking the query wherever there is a comma.
I tried this
How to write a value which contain comma to a CSV file in c#?
string query = "Insert into table(userId" +"\",\""+"companyID) values (" + userId + "\",\"" + SplitedLine[1] + ")";
writer.WriteLine(query);
But this is printing my insert commands in wrong format.
Please help.
Having tested this out, your simplest approach is to ensure that your query string is double quoted.
var query = $"\"Insert into table(userId,companyID values ({userId}, {SplitedLine[1]})\"";
I think the title of your question is ambiguous. You wanted to soround the values by quotation marks ("). But you made a mistake by escaping the " in the table part, it seams escaped " and not escaped was misked up.
Try to go with
string query = $"Insert into table(\"{userId}\",\"{companyID}\") values(\"{ userId}\",\"{SplitedLine[1]}\")";
This is my first project in c#. I have a little experience in Access VBA. I would like to move my apps over to be stand alone programs. I'm querying a table that has training types and dates. I would like to compare some of the types of training against each other based on the dates they were performed. The three training types are RWT010, RWP000, and RWT010BP. If RWT010BP exists and is newer it is the only one I need. Otherwise I need RWT010 and RWP000. I have figured out how to load the values into variables, but I need to be able to work with them. I would like the name of the dateTime value to be the trainType for the same row. That way I can compare them and output the right combination.
My old Access logic looked like this:
LABEL_DATE: IIf(IsNull([RWT010]),"RWT010BP: " & _
Format([RWT010BP],"Short Date"),IIf([RWT010BP]>[RWT010],"RWT010BP: " & _
Format([RWT010BP],"Short Date"),"RWT010: " & _
Format([RWT010],"Short Date") & " & " & "RWP000: " & _
Format([RWP000],"Short Date")))
This is how far I've gotten in c#:
Console.Write("Enter ID: ");
int idnum = Convert.ToInt32(Console.ReadLine());
string sql = "SELECT EXPID, TYPE, DATE_LATEST FROM TRAINING_TABLE where expid =" + idnum;
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
using (DbDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int expid = reader.GetInt32(0);
string trainType = reader.GetString(1);
DateTime trainDate = reader.GetDateTime(2);
It looks like the original Access logic has one DB row with three date fields, [RWT010], [RWT010BP], and [RWP000]. But in Oracle that's been normalized so you're getting back multiple rows, each of which has a a datetime field named [DATE_LATEST], and then name field called [TYPE] that's equal to "RWT010", "RWT010BP", or "RWP000".
And you were thinking, you want to handle those RWP000 date values by name, just like in Access. You were right, that's the clearest way to do it, and I'll show you how. I misunderstood what you were asking.
One way to do this would be to write an Oracle stored procedure that duplicates the Access logic. That's not the question you asked, but it's a legitimate way to do it. However, it would be more complicated than the Access version due to the change in the database, and anyway I haven't written Oracle SQL in years and I don't have an Oracle server handy to give me arbitrary, cryptic syntax errors about semicolons and whitespace.
So what I'm going to do is write a loop in C# to grab the datetimes from the DB rows and put them in local variables, and then duplicate the Access logic in C# using those variables instead of fields. It'll be a little verbose compared to the Access version, but sometimes that's how it goes.
int idnum = Convert.ToInt32(Console.ReadLine());
string sql = "SELECT EXPID, TYPE, DATE_LATEST FROM TRAINING_TABLE where expid =" + idnum;
// I don't know how you're using this so I'll just declare it here
// and leave that to you.
String dateLabel = "";
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
using (DbDataReader reader = cmd.ExecuteReader())
{
DateTime? RWT010 = null;
DateTime? RWT010BP = null;
DateTime? RWP000 = null;
// No need to check reader.HasRows. If it has no rows, reader.Read()
// will return false the first time, that's all.
while (reader.Read())
{
// Doesn't look to me like expid is used
//int expid = reader.GetInt32(0);
string trainType = reader.GetString(1);
DateTime trainDate = reader.GetDateTime(2);
switch (trainType) {
case "RWT010":
RWT010 = trainDate;
break;
case "RWT010BP":
RWT010BP = trainDate;
break;
case "RWP000":
RWP000 = trainDate;
break;
}
}
if (RWT010 == null || RWT010BP > RWT010) {
dateLabel = String.Format("RWT010BP: {0:d}", RWT010BP);
} else {
dateLabel = String.Format("RWT010: {0:d} & RWP000: {1:d}", RWT010, RWP000);
}
}
The original logic was this:
If RWT010 isn't null,
Do A
Otherwise, if RWT010BP > RWT010
ALSO do A
But if none of the above,
Do B
The first two branches do the exact same thing, so we can condense them both into one branch.
"Don't Repeat Yourself", as they say. You don't want to return to this code a year from now, wonder if those two lines were required to be the same, and then guess wrong or else not notice that they are the same, and only change one or the other. It's just a mess.
If you're not familiar with String.Format(), there's a lot to it. In the first argument string, {0} means "insert the second argument here"; {1} means "insert the third", and so on. The ":d" inside the curly braces is optional; it means to pass "d" as format information to the value its inserting. DateTime will interpret that "d" to mean "Short Date". You could also do it like this:
dateLabel = String.Format("RWT010BP: {0}", RWT010BP.Value.ToShortDateString());
Or like this:
dateLabel = "RWT010BP: " + RWT010BP.Value.ToShortDateString();
I have to use RWT010BP.Value in that line instead of just RWT010BP because RWT010BP is declared with a ? after it. That makes it a "nullable" value. A regular DateTime can't be null, but we need to accommodate nulls here.
If you're using C#6, you can do it like this, which I prefer. I didn't use it above because I don't know what version of C# you're on. Always prefer the least amount of "noise" cluttering up the code.
dateLabel = $"RWT010BP: {RWT010BP:d}";
That's the same ":d" as in String.Format("{0:d}", ...) above.
One more thing: idnum is an int, but don't ever concatenate a string value into a SQL string. That's a massive security vulnerability and people here will (rightly, I'm afraid) give you a very hard time for even contemplating it.
Use OracleCommand.Parameters instead, as shown in this answer. I would have used that even in this case, personally, just as a conditioned reflex.
i compare words of RichTextBox with database. but if i write word in richtextbox having single quotation then this program raise Exception.
Example
who resort to primitive and barbaric methods to kill 'Israeli's.
In this Sentence the Word 'Israeli's having single quotation so this word break the program.
i writes the following code.
private void btnSeparte_Click(object sender, EventArgs e)
{
string MyConString = "server=localhost;" +
"database=sentiwordnet;" + "password=zia;" +
"User Id=root;";
MySqlConnection con = new MySqlConnection(MyConString);
string line = rtbEmotion.Text;
Regex replacer = new Regex(#"\b(is|are|am|could|will|the|you|'|not|I|in)\b|(\b\d\b)");
line = replacer.Replace(line, "");
string[] parts = Regex.Split(line, " ");
foreach (string part in parts)
{
MySqlCommand cmd = new MySqlCommand("select * from score where Word='" + part + "'", con);
con.Close();
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
if (r.Read())
{
txtBxPosEmot.Text = r["Pos"].ToString();
TxtBoxNeg.Text = r["Neg"].ToString();
pos = Convert.ToDouble(txtBxPosEmot.Text);
neg = Convert.ToDouble(TxtBoxNeg.Text);
listView1.Items.Add(part);
listView1.Items.Add(pos.ToString());
listView2.Items.Add(part);
listView2.Items.Add(neg.ToString());
pos1 = pos + pos1;
neg1 = neg + neg1;
r.Close();
con.Close();
}
else
{
textBox1.Text = "";
txtbPosSyth.Text = "";
r.Close();
con.Close();
}
}
}
Exception
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Israels'' at line
This is classic SQL injection. In SQL, statements are encased in single quotes... So your single quote ends your statement prematurely since you're not escaping it. This also leaves you vulnerable to attack from malicious users. You must use parameterized SQL to avoid it. See: http://www.dotnetperls.com/sqlparameter
In case you were wanting an explanation for the behavior that you're seeing, your regex isn't catching the ' in your input because it has to be surrounded by a word boundary, which in your case, it's not.
the reason your regex breaks is because ' causes a word boundary itself, so it has to be surrounded by letters.
your regex doesn't account for this.
Description
If you're looking to replace just the ' trapped inside a word, then you could use the following regex.
(?<=\w\b)['](?=\b\w)
Example
This php routine is included to simply show how the regex works.
<?php
$sourcestring="She said 'hi, this is Sam's house'.
'The 'quick red f'ox jumpe'd over the 'laz'y brown dog.'";
echo preg_replace('/(?<=\w\b)[\'](?=\b\w)/im','',$sourcestring);
?>
$sourcestring after replacement:
She said 'hi, this is Sams house'.
'The 'quick red fox jumped over the 'lazy brown dog.'
My C# Console Applcation:
1:
string CE_ParentName_ = CEReader5[0].ToString(); // get string with lithuanian letters for example "KonsolÄ—s".
if I use Console.WriteLine() , I get correct output in console.
2:
readname.CommandText = "SELECT [ID] FROM [Net7].[dbo].[GroupFilter] WHERE
[GroupFilterName]='" + CE_ParentName_ + "'"; // I need to find records in my DB with name of that string (1 possible option)
3:
if (NameReader.Read()) { idd = NameReader[0].ToString(); } // if i get any results ar no.2 i need to read them
The point is that no.2 returns zero results if string contains lithuanian letters. If string is w/o lithuanian letters - everything works perfect. Tried everything, you are my last hope folks.
Are Lithuanian characters multibyte? (like Japanese for example)
Is the GroupFilterName NVARCHAR or VARCHAR? If it's NVARCHAR, perhaps you need to put N in front of the string.
Eg.
readname.CommandText = "SELECT [ID] FROM [Net7].[dbo].[GroupFilter] WHERE
[GroupFilterName]=N'" + CE_ParentName_ + "'";
And see asawyer's comment regarding avoiding injection attacks.
Im importing a csv to my sql server table using the following code
SqlCommand nonqueryCommand = myConnection.CreateCommand();
nonqueryCommand.CommandText =
"INSERT INTO MYTABLE VALUES(#num1, #num2,#num3,#num4)";
nonqueryCommand.Parameters.Add("#num1",SqlDbType.Decimal);
nonqueryCommand.Parameters.Add("#num2", SqlDbType.Decimal);
nonqueryCommand.Parameters.Add("#num3", SqlDbType.Decimal);
nonqueryCommand.Parameters.Add("#num4", SqlDbType.Decimal);
nonqueryCommand.Parameters["#num1"].Value = crntRecord[0];
nonqueryCommand.Parameters["#num2"].Value = crntRecord[1];
nonqueryCommand.Parameters["#num3"].Value =crntRecord[3];
nonqueryCommand.Parameters["#num4"].Value = crntRecord[4];
nonqueryCommand.ExecuteNonQuery();
where the parameter 3 and 4 are of type decimal(9,6) in the DDL when i execute the code at ExecuteNonQuery i get the following exception
Failed to convert parameter value from a String to a Decimal.
please help me find out the problem tnx.
EDIT
the value in the crntRecord[3] looks like
Assuming that crntRecord is an array of strings, you need to parse the strings to a decimal first.
Ex:
nonqueryCommand.Parameters["#num3"].Value = decimal.Parse(crntRecord[3].ToString());
Note that this will throw an exception if crntRecord[3] is not parseable to a decimal; if that's a situation that could occur, look into decimal.TryParse() instead.
Edited to use safer parsing methods
Your strings have surrounding quotes that you need to strip off. Try
decimal num3;
bool isDecimal = decimal.TryParse(crntRecord[3].Trim(new []{'\"'}), out num3);
if(isDecimal)
nonqueryCommand.Parameters["#num3"].Value = num3;
I would recommend using this method for all of your decimals, which would mean putting this logic in a reusable function would be a rise refactoring.
try with
nonqueryCommand.Parameters["#num1"].Value = Convert.ToDecimal(crntRecord[0]));
nonqueryCommand.Parameters["#num2"].Value = Convert.ToDecimal(crntRecord[1]);
nonqueryCommand.Parameters["#num3"].Value =Convert.ToDecimal(crntRecord[3]);
nonqueryCommand.Parameters["#num4"].Value = Convert.ToDecimal(crntRecord[4]);
Use
nonqueryCommand.Parameters.AddWithValue("#num1", crntRecord[0]);