I am making a C# client-server application for my college class.
I have an MS Access database with a table Package, it has some values like 'name', 'dateFrom', 'dateTo', and 2 values called 'internet' and 'telephone' which are YES/NO type
In the program I made a class Package and set internet and telephone as bool type of data. Firstly, is this correct? If value is set as YES/NO in MS Access, am I supposed to set it as bool in C#? this seems logical to me..
Secondly, when I enter SQL command for inserting these values I get an error, I don't know how to send bool values to database
Here is my code
command.CommandText = "Insert into Package values ("+p.PackageID+", '"+ p.Name+"', '"+p.DateFrom.ToString()+"', '"+p.DateTo.ToString()+"', "+Convert.ToBoolean(p.Internet.ToString())+", "+Convert.ToBoolean(p.Telephone.ToString())+")";
command.ExecuteNonQuery();
I tried a lot of things, and this was my last attempt of converting values to be able to insert them.. but it doesn't work..
I always get System.InvalidOperationException
For various reasons, you SHOULD NOT USE string concatenation on SQL statements. Use parameters. Try like:
command.CommandText = "Insert into Package values (#param1,#param2#param3,#param4,#param5,#param6)";
command.Parameters.Add("#param1", OleDbType.Integer).Value = p.PackageID;
command.Parameters.Add("#param2", OleDbType.VarWChar).Value = p.Name;
command.Parameters.Add("#param3", OleDbType.Date).Value = p.DateFrom;
command.Parameters.Add("#param4", OleDbType.Date).Value = p.DateTo;
command.Parameters.Add("#param5", OleDbType.Boolean).Value = bool.Parse(p.Internet.ToString());
command.Parameters.Add("#param6", OleDbType.Boolean).Value = bool.Parse(p.Telephone.ToString());
command.ExecuteNonQuery();
Related
I'm trying to insert a data into a table that comes from another table - something like this:
decimal saldo = getDbSaldo($#"SELECT Balance FROM clients WHERE Pin='{pin}' AND CardNumber = '{numeroCartao}'");
insertExtrato($#"insert into MoveInfo (CardNumber, Deposit, Saldo, Withdraw, DataHora) Values({numeroCartao}, {deposit}, {saldo}, {withdraw}, getDate())");
The data is getting there:
But when I get it working, I always get this error:
I've been stuck on this for two days.
Now is the time to replace your SQL-injectable code with parameterized queries.
What's happening is that you're not controlling your SQL code. You're munging strings together and executing them as code. The result could be valid SQL code, could be invalid SQL code, could be malicious, could be anything. You're not in control of it so you don't know.
Always add values as parameters. An example would be:
var query = "insert into MoveInfo (CardNumber, Deposit, Saldo, Withdraw, DataHora) Values(#numeroCartao, #deposit, #saldo, #withdraw, getDate())";
var cmd = new SqlCommand() { Connection = cn, CommandText = query };
cmd.Parameters.Add("#numeroCartao", SqlDbType.Int).Value = numeroCartao;
cmd.Parameters.Add("#deposit", SqlDbType.Decimal).Value = deposit;
cmd.Parameters.Add("#saldo", SqlDbType.Decimal).Value = saldo;
cmd.Parameters.Add("#withdraw", SqlDbType.Decimal).Value = withdraw;
cmd.ExecuteNonQuery();
Note that I completely guessed on the SqlDbType values to use here. You'll of course want to use whatever matches your database schema.
I want to use the following SQL statement in a small C# application.
The SQL statement runs perfect in Access 2013.
INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin("id", "FIGURE", "char_name='Doe' AND forename='John'"),
DMin("id", "DIALOG", "speaker=3 AND dialog_text='some text'")
);
When i try to run the following C# code, i get a "Too few parameters" exception, i tripple checked the spelling, i even copied the string from the Access query.
Changing the single quotes in double quotes did not work, i got the same exception. Is it even possible to run this query within C#?
Other queries are working fine.
string addListeners = #"INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin('id', 'FIGURE', 'char_name =? AND forename =?'),
DMin('id', 'DIALOG', 'speaker=? AND dialog_text=?')
); ";
foreach (Character listener in d.addressed_to)
{
using (OleDbCommand cmd = new OleDbCommand(addListeners, dbConn))
{
cmd.Parameters.AddWithValue("?", listener.name);
cmd.Parameters.AddWithValue("?", listener.forename);
cmd.Parameters.AddWithValue("?", speakerID);
cmd.Parameters.AddWithValue("?", d.dialog_text);
cmd.ExecuteNonQuery();
}
}
Changing the string to the following as suggested did not work:
#"INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin(""id"", ""FIGURE"", ""char_name =? AND forename =?""),
DMin(""id"", ""DIALOG"", ""speaker=? AND dialog_text=?"")
); ";
The exception:
An exception of type 'System.Data.OleDb.OleDbException' occurred in
System.Data.dll but was not handled in user code
Additional information: Too few parameters. Expected 2.
It looks rather ugly, but this works for me using Provider=Microsoft.ACE.OLEDB.12.0:
string addListeners =
#"INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin('id', 'FIGURE', 'char_name=""' & ? & '"" AND forename=""' & ? & '""'),
DMin('id', 'DIALOG', 'speaker=' & ? & ' AND dialog_text=""' & ? & '""')
); ";
using (var cmd = new OleDbCommand(addListeners, dbConn))
{
cmd.Parameters.Add("?", OleDbType.VarWChar, 255).Value = "Doe";
cmd.Parameters.Add("?", OleDbType.VarWChar, 255).Value = "John";
cmd.Parameters.Add("?", OleDbType.Integer).Value = 3;
cmd.Parameters.Add("?", OleDbType.VarWChar, 255).Value = "some text";
cmd.ExecuteNonQuery();
}
It also works okay with
cmd.Parameters.Add("?", OleDbType.VarWChar, 255).Value = "O'Reilly";
but it does fail if the text parameter value contains solitary double-quotes. :(
You can avoid the quote challenges with DMin(), and injection risk, by switching from an INSERT ... VALUES to an INSERT ... SELECT statement.
INSERT INTO adressed_to (dialog,listener)
SELECT
Min(FIGURE.id) AS dialog,
(
SELECT Min(id)
FROM DIALOG
WHERE speaker=[p1] AND dialog_text = [p2]
) AS listener
FROM FIGURE
WHERE FIGURE.char_name=[p3] AND FIGURE.forename=[p4];
I used [p1] through [p4] as the parameter names to indicate the order Access will expect to receive the parameter values. In your version of the query, you can substitue ? for each parameter name.
I don't think that you can do it like this.
Yes, OLE DB supports named parameters. However, these parameters can only be used where a value is expected, not inside a value. Let me show what I mean by way of an example:
This works: SELECT a FROM myTable WHERE b = ?
This doesn't: SELECT a FROM myTable WHERE b = 'X ? Y'
In the first example, ? serves as a placeholder for a value. In the second example, ? is a literal question mark inside a string.
What you are doing matches the second example:
INSERT INTO adressed_to (dialog)
VALUES (
SomeMethod("foo", "bar", "foobar ? baz"),
);
OLE DB has no idea that DMin is a special function for Access databases which provides some kind of dynamic SQL functionality. All it sees is that you are using a string literal with question mark inside. Thus, the question mark has no special meaning.
Personally, I would try to rewrite the INSERT INTO ... VALUES ... to an INSERT INTO ... SELECT ... statement which uses standard SQL aggregation methods instead of the Access-specific domain aggregate functions.
(If all else fails and you decide to use string concatenation instead of parameters: Please do proper escaping and input sanitation to avoid SQL injection.)
What is happenning is you keep adding params to this command object at each iteration, that is a problem, you should only add it once before the loop, and then assign it a different value inside of the loop.
string addListeners = #"INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin('id', 'FIGURE', char_name =#CharName AND forename =#Forename),
DMin('id', 'DIALOG', speaker=#Speacker AND dialog_text=#DialogText)
); ";
using (OleDbCommand cmd = new OleDbCommand(addListeners, dbConn))
{
cmd.Parameters.Add("#CharName", SqlDbType.VarChar);
cmd.Parameters.Add("#Forename", SqlDbType.VarChar);
cmd.Parameters.Add("#Speacker", SqlDbType.VarChar);
cmd.Parameters.Add("#DialogText", SqlDbType.VarChar);
foreach (Character listener in d.addressed_to)
{
cmd.Parameters["#CharName"].Value = listener.name;
cmd.Parameters["#Forename"].Value = listener.forename;
cmd.Parameters["#Speacker"].Value = speakerID;
cmd.Parameters["#DialogText"].Value = d.dialog_text;
cmd.ExecuteNonQuery();
}
}
PS:
Note Im not sure when if you can use named placeholder or not using Oledbcommand, but you should get my point
I don't think this is going to work like you want it to. In order for you to effectively test this you need access to prompt you for a parameter when you test the query in Access.
So I can run this
INSERT INTO adressed_to (dialog,listener)
VALUES (
DMin("id", "FIGURE", "char_name='" & pchar_name& "' AND forename='" & pforename & "'"),
DMin("id", "DIALOG", "speaker="& pSpeaker & " AND dialog_text='" & pDialog_text & "'")
);
and get the popups which means that when you connect over OLEDB the parameters will also be anticipated.
The disadvantage here is that you are basically making dynamic SQL and not a true parameterized query. Though I expect it is ok because Access will only process one query at a time. i.e. you're not going to do much SQL injection here because ACE will throw an exception.
Heinzi is right though, the D* functions are not available outside of Access (i.e. when connecting directly to ACE like you would be via OleDb). These are VBA functions and that is not in context for ACE. You can write your query as straight SQL.
INSERT INTO adressed_to (dialog,listener)
Select (select min(id) from Figure where char_name= pchar_name AND forename= pforename)
, (Select min(id) from DIALOG where speaker= pSpeaker AND dialog_text=pDialog_text) T
This is for a website in C#,Visual Studio 2010.
I've created a form with many textboxes, a date picker, dropdownlist, etc.
I've created a table in sqlplus with the columns with necessary types(varchar, number, date).
When I click the submit button in my form, I want to store the data in the table I've created.
Just to make it simpler for you guys, assume I have 3 text boxes
(name(text), id, date(i've printed the date in the text box as string)).
When I click submit it should fill the table with these data.
Im struggling to get the OracleCommand to execute this.
cmd = new OracleCommand(______, con);
If there is any other way I can do this by manipulating the types also its welcome :)
The insert syntax for oracle commands generally follows the pattern;
string query = #"INSERT INTO SOME_TABLE VALUES (SOME_COLUMN_1 = :SomeParam1,SOME_COLUMN_2 = :SomeParam2 )";
OracleCommand command = new OracleCommand(query, connection) { CommandType = CommandType.Text };
command.Parameters.Add(":SomeParam1", OracleDbType.Varchar2).Value = "Your Val 1";
command.Parameters.Add(":SomeParam2", OracleDbType.Varchar2).Value = "Your Val 2";
connection.ExecuteNonQuery();
See more reference examples here;
Using Named Parameters with Oracle ODP.NET
I am currently entering data into a database from a calendar, and I have realized that any new entry I input turns out to be null. All of the data entered is of the same dataype as the column, and I'm confused to as how this is happening. None of the values I'm inputting are null or empty. I have debugged and watched the values to know that.
public static void insertEvent(string date, string title, string eventLocation, string detailsShort, string detailsLong, DateTime startTime, DateTime endTime, DateTime entered, string enteredBy)
{
try
{
string queryString = "INSERT INTO cor(cal_date,event_title,event_location,details_short,details_long,time_start,time_end,entered,entered_by) VALUES (cal_date=cal_date, event_title=event_title, event_location=event_location, details_short=details_short, details_long=details_long,time_start=time_start, time_end=time_end, entered=entered, entered_by=entered_by)";
OdbcConnection conn = new OdbcConnection(MyConString);
conn.Open();
OdbcCommand command = new OdbcCommand(queryString, conn);
command.Parameters.Add("cal_date", OdbcType.DateTime, 30).Value = date;
command.Parameters.Add("event_title", OdbcType.VarChar, 100).Value = title;
command.Parameters.Add("event_location", OdbcType.VarChar, 100).Value = eventLocation;
command.Parameters.Add("details_short", OdbcType.VarChar, 300).Value = detailsShort;
command.Parameters.Add("details_long", OdbcType.VarChar, 300).Value = detailsLong;
command.Parameters.Add("time_start", OdbcType.DateTime, 30).Value = startTime;
command.Parameters.Add("time_end", OdbcType.DateTime, 30).Value = endTime;
command.Parameters.Add("entered", OdbcType.DateTime, 30).Value = entered;
command.Parameters.Add("entered_by", OdbcType.VarChar, 30).Value = enteredBy;
command.ExecuteNonQuery();
conn.Close();
}
catch (Exception)
{
}
}
INSERT INTO cor(cal_date, ...) VALUES (cal_date=cal_date, ...);
The problem is the expression cal_date=cal_date (and similar expressions for every column).
As you're inserting a new row, there is no value for any column yet. So any reference to the column is NULL. The expression NULL=NULL also yields NULL. So you're not inserting values, you're inserting NULL expressions for all columns.
If you change the expression to cal_date=#cal_date it doesn't fix the problem. You're comparing the current value for cal_date (which is NULL) to the value of the parameter #cal_date. An expression like NULL=<anything> always yields NULL.
You should just use parameters, not expressions:
INSERT INTO cor(cal_date, event_tile, ...) VALUES (#cal_date, #event_title, ...);
update: Read the example code in "Pass Parameters to OdbcCommand". That example shows using ? placeholders as #ZombieHunter's answer recommends -- not named parameter placeholders. However, when calling Parameters.Add(), somehow one uses the named parameter with # prefix. Go figure.
nonqueryCommand.CommandText = "INSERT INTO MyTable VALUES (?, ?)";
nonqueryCommand.Parameters.Add("#MyName", OdbcType.VarChar, 30);
nonqueryCommand.Parameters.Add("#MyNumber", OdbcType.Int);
I'm not sure if ODBC supports named parameters together regular SQL statements. The ODBC statements I've seen so far use "?" as placeholder for the parameters.
Certain DBMSs allow an application to specify the parameters to a
stored procedure by name instead of by position in the procedure call.
Such parameters are called named parameters. ODBC supports the use of
named parameters. In ODBC, named parameters are used only in calls to
stored procedures and cannot be used in other SQL statements.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms715435%28v=VS.85%29.aspx
Why don't you use the native MySQL provider for .NET? That would be much faster and probably supports more MySQL specific features.
Also I strongly recommend not using empty catch blocks unless you have a good reason for "consume" that exception.
I'm writing a method to insert a Student into a local SQL database that contains a table with information about Students:
public void AddStudent(string name, string teachName, string pass)
{
string dbfile = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\Logo.sdf";
SqlCeConnection connection = new SqlCeConnection("Data Source=" + dbfile + "; Password = 'dbpass2011!'");
connection.Open();
SqlCeTransaction transaction = connection.BeginTransaction();
SqlCeCommand command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO Students VALUES ('#name', '#id', '#pass', '#tname')";
command.Parameters.Add("#name", name);
command.Parameters.Add("#id", this.ID);
command.Parameters.Add("#pass", MD5Encrypt.MD5(pass));
command.Parameters.Add("#tname", teachName);
command.Prepare();
command.ExecuteNonQuery();
transaction.Commit();
connection.Dispose();
connection.Close();
}
Whenever I use this, it never inserts the data to the table when I look at the contents of the Students table in the database. Originally I had this return an int so I could see how many rows it affected, which it always returned 1, so I know it's working.
I've looked for answers to this, and the answer to similar questions was that the person asking was looking at the wrong .sdf file. I've made sure that I'm looking at the right file.
Any feedback would be much appreciated!
command.CommandText = "INSERT INTO Students VALUES ('#name', '#id', '#pass', '#tname')";
You should remove the extra single quotes - this should be:
command.CommandText = "INSERT INTO Students VALUES (#name, #id, #pass, #tname)";
Also I am not sure why you open a transaction for a single insert - that is also not needed.
You don't need to put single quote to parametrized query, in case of parametrized query the whole data will be parsed as required,
command.CommandText = "INSERT INTO Students VALUES (#name, #id, #pass, #tname)";
Also, its better to set parameter type, size and value explicitly as below:
SqlCeParameter param = new SqlCeParameter("#name", SqlDbType.NVarChar, 100);
param.Value = name; // name is a variable that contain the data of name field
//param.Value = 'Jhon Smith'; //Directly value also can be used
Hope this would be helpful, thanks for your time.
There is most likely an exception being raised in your code; you need to add a try/catch handler and/or debug the application to figure out exactly what is happening.
However, there are at least two issues with your code:
The prepare statement requires the data types of the parameters. From the MSDN documentation:
Before you call Prepare, specify the data type of each parameter in the statement to be prepared. For each parameter that has a variable-length data type, you must set the Size property to the maximum size needed. Prepare returns an error if these conditions are not met.
You need to close the connection before disposing it (this won't affect the insert, however).