I need to have a second copy of a MS Access table that will be saved in a network drive. And since splitting is not an option because it drastically slows the application down, I decided to just manually "merge" the data after a certain user action like clicking an exit button.
I have this query string
public const string MERGETOMAIN = #"INSERT INTO tbl_name (UserID, ...)" +
" IN 'C:\Users\nathan\Desktop\copy.accdb' SELECT TOP 1 UserId, ... " +
" FROM tbl_name WHERE UserID = #currentUser ORDER BY ROWID DESC";
...and it works when I do this:
using (OleDbCommand cmd = new OleDbCommand(Helpers.Queries.MERGETOMAIN, mergeConn))
{
cmd.Parameters.AddWithValue("#currentUser", currentUserID);
cmd.ExecuteNonQuery();
}
But, as you notice, the path to the copy is hardcoded. I wanted it to be dynamic so I tried using a parameter like I always do, so I replaced it with a question mark:
public const string MERGETOMAIN = #"INSERT INTO tbl_name (UserID, ...)" +
" IN ? SELECT TOP 1 UserId, ... " +
" FROM tbl_name WHERE UserID = #currentUser ORDER BY ROWID DESC";
But this results in the following error:
Your network access was interrupted. To continue close the database and then open it again.
So instead of a question mark, I used #parameterName. But, when I do, I get the following error:
The file "foo\foo\#parameterName" cannot be found.
The weird thing is, the other paremeter, #currentUser, is working just fine.
I'm not really sure what is happening here, but the only thing that works right now is to hardcode the path. I tried looking through similar questions but no dice.
Any idea will be greatly appreciated.
Thank you.
You can write a method which creates the string for you.
public string getMergeToMain(string path)
{
string strRet;
if (path != null)
{
strRet = #"INSERT INTO FSO_LogSheet (UserID, ...)" +
" IN '" + path + "' SELECT TOP 1 UserId, ... " +
" FROM FSO_LogSheet WHERE UserID = #currentUser ORDER BY ROWID DESC";
return strRet;
}
else
{ //Error, not agood habit to return null...
return null;
}
}
With the method parameter "path", you can set the path dynamically.
You can call it for example by
OleDbCommand cmd = new OleDbCommand(fooClass.getMergeToMain(#"C:\users\bar.accdb"), mergeConn)
I assume that you know the difference between public, private and static methods, so please do not forget to set it right for your own needs.
Related
the code is below and the error starting from sqlCommand cmd the 13th line of this code
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
Con.Open();
String query = "update Student_tbl set StdName='" + StudName.Text + "',where FatherName='" + FtName.Text + "',where MotherName='" + MtName.Text + "',where StdAddress='" + Address.Text + "',where Collage ='" + Collage.Text + "'set StdRoom = " + StRmNum.SelectedValue.ToString()+",StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where StdUsn ='"+StudenUsn+ "')";
SqlCommand cmd = new SqlCommand(query, Con);
cmd.ExecuteNonQuery();
MessageBox.Show("Room Successfully Updates");
Con.Close();
FillStudentDGV();
}
}
Your code should look more like:
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
var query = #"
update Student_tbl
set
StdName=#sn,
FatherName=#fn,
MotherName=#mn,
StdAddress=#sa,
Collage=#c,
StdRoom=#sr,
StdStatus=#ss
where
StdUsn=#su";
using var con = new SqlConnection(YOUR_CONN_STR_HERE);
using var cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue(#sn, StudName.Text);
cmd.Parameters.AddWithValue(#fn, FtName.Text);
cmd.Parameters.AddWithValue(#mn, MtName.Text);
cmd.Parameters.AddWithValue(#sa, Address.Text);
cmd.Parameters.AddWithValue(#c, Collage.Text);
cmd.Parameters.AddWithValue(#sr, StRmNum.SelectedValue);
cmd.Parameters.AddWithValue(#ss, StudSt.SelectedItem);
cmd.Parameters.AddWithValue(#su, StudenUsn);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Room Successfully Updates");
FillStudentDGV();
}
}
There are good reasons to avoid using AddWithValue if you use SQLServer which you can get into at a later date if you want, but it's convenient for me (who doesn't know the types and widths of your columns) dealing with the current massive elephant in the room which is your SQL is massively vulnerable to a hacking technique known as sql injection (and to a lesser extent it would blow up with an error for any student whose name included an apostrophe) - using AddWithValue might make your query slightly slower, but better that than it be the cause of the next data breach; learn how to write SQLs right, right now
Never ever take data supplied by a user and concatenate it into an SQL string. Doing so essentially, in most cases, gives the user access to your database. So many big companies whose developers should know better, put up expensive firewalls and security and then let anyone in via this back door anyway; sql injection prone systems are one of the leading causes of hacks in the world today
Always use #parameter placeholders in the SQL for user data and add a parameter to the command's parameters collection, containing the data
Now on the topic of your actual error; the pattern for an update is
update table
set col1=#param1, col2=#param2 ...
where (some conditions)
You have one where and one set. If there is some conditional aspect to your set, like you only want to update the student name/address if it is currently null then you can do like:
update table
set
name=case when name is null then #n else name end,
address=case when address is null then #a else address end
where (some conditions)
Or more simply
update table
set
name=coalesce(name, #n)
address=coalesce(address, #a)
where (some conditions)
You can't mix n match and say "where this=that where this2=that2 set this3=that3" - that's a syntax error. Where is for picking the row you want to update and set is for starting a block of commas separated columns and values the row data is to be updated to.
Strive to write your sql nicely formatted inside an #string; it's a programming language all of its own, and will be easier to debug if it's laid out nicely
Can u try with it ?
String query = "update Student_tbl set StdName='" + StudName.Text + "',StdRoom = '" + StRmNum.SelectedValue.ToString()+"',StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where FatherName='" + FtName.Text + "' and MotherName='" + MtName.Text + "' and StdAddress='" + Address.Text + "' and Collage ='" + Collage.Text + "' and StdUsn ='"+StudenUsn+ "'";
i have the following table in MySql :
ID Name
1 Google
2 Yahoo
3 Facebook
4 Whatever
I have a textfield that when someone writes something and presses a button it stores this value in a string. This string is the Name of the above table. Then i have my code about selecting the id referred to that name. Ex, if the user enters Facebook i will find that the ID = 3. this is the code :
public bool FindCompanyID(string companyName)
{
return ExecQuery("select id from companies where name=#name",
cmd =>
{
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
return cmd;
});
}
I want someone to show me a sample of code about the following : Saving to a string the " id " . if the ID in the database = 2 i want to make a
int Company_Number_ID
that i will use. How can i get the string to read the specified value from the database?
I am guessing your return type is bool to check whether the DDL statements were executed successfully.
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
try
{
dbConn.Open();
Company_Number_ID = (Int32)cmd.ExecuteScalar();
} catch (Exception e) {
//Exception occured. Handle it here
}
Note: cmd.Parameters.AddWithValue("#companyName",companyName).
this is more secure
Edit: As pointed out in the comment by user3185569 , ExecuteScalar is better if you are sure it'll return only one row. But since no such information was provided. I did not consider that.
You can use ExecuteScalar directly like this.
Company_Number_ID = (Int32)cmd.ExecuteScalar();
I get this run time error and my id is not null I checked it in my code which you will see and I'm using telerik GridView
this is the run time error
The parameterized query '(#_fName nvarchar(4),#_lName nvarchar(2),#_phone nvarchar(6),#_a' expects the parameter '#_id', which was not supplied.
I'm trying to get the id from another form that's why I wrote it like this
here's my code in my first layer
private void btnEdt_Click(object sender, EventArgs e)
{
Ref_View_Model = new View_model._View_Model();
Ref_C = new Customers();
foreach (var RowInfo in Ref_C.radGridView1.SelectedRows)
{
FireCell = RowInfo.Cells[0].Value.ToString();
if (FireCell==null)
{
MessageBox.Show("null");
}
}
//Ref_C.radGridView1.CurrentRow.Delete();
Ref_C.customersTableAdapter.Update(Ref_C.sales_and_Inventory_SystemDataSet);
Ref_C.customersTableAdapter.Fill(Ref_C.sales_and_Inventory_SystemDataSet.Customers);
Ref_View_Model.GetEditCustomers(FireCell, txtFName.Text, txtLName.Text, txtPhn.Text, txtDdrss.Text);
}
here's my code in the last layer
public void EditCustomres( string _id,string _fName, string _lName,string _phone, string _address)
{
Connection_String = #"Data Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=TrueData Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=True;";
Query = "update Customers " +
"set FName=#_fName ,LName=#_lName ,Phone=#_phone ,[Address]=#_address" +" "+
"where Id like #_id";
using (Con=new SqlConnection(Connection_String))
using (Cmd=new SqlCommand(Query,Con))
{
Cmd.Parameters.Add("#_fName", SqlDbType.NVarChar);
Cmd.Parameters.Add("#_lName", SqlDbType.NVarChar);
Cmd.Parameters.Add("#_phone", SqlDbType.NVarChar);
Cmd.Parameters.Add("#_address", SqlDbType.NVarChar);
Cmd.Parameters.Add("#_id", SqlDbType.Int);
Con = Cmd.Connection;
Con.Open();
Cmd.Parameters["#_fName"].Value = _fName;
Cmd.Parameters["#_lName"].Value = _lName;
Cmd.Parameters["#_phone"].Value = _phone;
Cmd.Parameters["#_address"].Value = _address;
Cmd.Parameters["#_id"].Value = _id;
Cmd.ExecuteNonQuery();
Cmd.Dispose();
}
}
You really don't want to use LIKE in this case, unless you have very specific needs for it to update things that look like the ID you're passing in, but are not quite it...
You're passing in #_id as an SqlDbType.Int, but the variable is actually of type string, this will cause a conversion to happen under the hood. In case you're passing in an empty string, the value is converted to null, which will result in the error you mentioned in your post. Check the code that leads into calling EditCustomres to ensure that it actually passes in the correct value. Adding argument checks, like the one I added, will help you track these kinds of issues much earlier in the callstack.
Step one is to get rid of your LIKE statement, so please update the query to use:
where id = #_id
Then update your code, since you expect the _id variable to be in int, you can't just assign a string to it, which is probably why it's getting reset to null. Either update the method to accept an int parameter instead of string id, or parse the int in your method before adding the parameter:
int idValue = -1;
if (!int.TryParse(_id, NumberStyles.Integer, CultureInfo.InvariantCulture, out idValue))
{
throw new ArgumentException("id", "Id must be a string which contains an integer value, the value of 'id' was: '" + _id + "'");
}
Cmd.Parameters.Add("#_id", SqlDbType.Int).Value = idValue;
You may need to add a using statement to your file:
using System.Globalization;
This is where NumberStyles and CultureInfo are defined. Normally Visual Studio will suggest where you can find these items crtl+. will pop-up a screen which will add this statement automatically.
End result would be:
using System.Globalization;
....
....
public void EditCustomers( string _id,string _fName, string _lName,string _phone, string _address)
{
int idValue = -1;
if (!int.TryParse(_id, NumberStyles.Integer, CultureInfo.InvariantCulture, out idValue))
{
string message = "Id must be a string which contains an integer value, the value of 'id' was: '" + _id + "'";
throw new ArgumentException("_id", message);
}
Connection_String = #"Data Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=TrueData Source=MOSTAFA-PC;Initial Catalog=" + "Sales and Inventory System" + ";Integrated Security=True;";
Query = #"update Customers
set FName=#_fName, LName=#_lName, Phone=#_phone,[Address]=#_address
where Id = #_id";
using (Con=new SqlConnection(Connection_String))
using (Cmd=new SqlCommand(Query, con))
{
Cmd.Parameters.AddWithValue("#_fName", _fName);
Cmd.Parameters.AddWithValue("#_lName", _lName);
Cmd.Parameters.AddWithValue("#_phone", _phone);
Cmd.Parameters.AddWithValue("#_address", _address);
Cmd.Parameters.AddWithValue("#_id", idValue);
Con.Open();
Cmd.ExecuteNonQuery();
}
}
I simplified the code a bit as well. using a verbatim string for your SQL statement, removing the call to Dispose (which is already covered by your use of using(cmd) and removing the Con=Cmd.Connection, since it really cannot have any other value.
Using the .AddWithValue method is also easier than creating and setting the value individually.
Be really careful with solutions that require you to concatenate your string to form the SQL query on the SQL Server side, this could result in the value injecting unwanted SQL statements that can expose your data to the outside world or allow outsiders to destroy your data.
Also be careful with LIKE statements for matching update values. Unless you have very strong argument validation on the code paths calling into this statement, passing in id="?" or id="%%" or simply id=string.Empty to your function would likely update all records and will thus overwrite all of them to have the same values. %1% will match 1, 10, 21, 31, 11, 100003... Which is highly unlikely the desired behavior.
Using = over like in delete and update statements is almost always the desired solution. If you get errors with = you're likely mixing data types (string where int is expected for example).
Your LIKE clause for id is incorrect. It should be like this:
Id LIKE '%' + #_id + '%'
Or:
Cmd.Parameters.AddWithValue("#_id","%" + _id+ "%");
Or:
Cmd.Parameters.Add("#_id", SqlDbType.Int).Value = "%" + _id + "%";
Although it would be better that you use simple = instead of Like:
where Id = #_id
I've got a problem with my ASP.NET application when I'm trying to log in a user. The issue is that when I'm trying to run the query, an exception gets thrown which says the tale name is invalid. It's because the table is called USER, which is a part of SQL.
I'm not in a position where I can change the table name.
public bool LoginUser(string username, string password)
{
//Database Connectie maken
DBConnectionOpen();
string query = #"SELECT NICKNAME, PASSWORD FROM " + "'USER'" + "WHERE NICKNAME = '" + username + "'";
bool result = false;
try
{
OracleCommand command = new OracleCommand(query, conn);
OracleDataReader reader = command.ExecuteReader();
Console.WriteLine("*Query Uitvoeren*");
reader.Read();
if (username + password == reader.GetString(0) + reader.GetString(1))
{
result = true;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
return result;
}
Whomever named the table "USER" should have db privs removed, but I think you just need to add double quotes around the table name:
select * from "USER" where ...
Note that its case sensitive when you add the double quotes, so if the table is named User you'd need "User" instead of "USER"
Thanks for all the response, but I finally figured it out.
What the query should have been:
string query = #"SELECT NICKNAME, ""PASSWORD"" FROM ""USER"" WHERE NICKNAME = '" + username + "'";
You are querying on the string value 'USER'.
You should use
string query = #"SELECT NICKNAME, PASSWORD FROM [USER] WHERE NICKNAME = '" + username + "'";
This will query on the table called USER. In SQL normally you use brackets to indicate you are querying on an object if what you mean can be ambiguous.
The concatenation of the table name as a string is unnecessary so I left it out. If you change it to a variable it can be useful.
In addition instead of concatenating username maybe you should also use alternative for Oracle what is called SqlParameter for SQL Server, to avoid SQL injection.
Try to correct your SQL statement like the following:
string query = "SELECT NICKNAME, PASSWORD FROM [USER] WHERE NICKNAME = '" + username + "'";
Also, if you are using SQL reserved word (e.g. DATE) as a Column name, then enclose it in angular brackets (like [DATE]) in your SQL statement.
Hope this may help.
I use the following code to insert a record from one database to another but it doesn't work. I tried the query in MS-ACCESS 2007 and it works fine but it doesn't work when called programmatically from my C# code?
string query_insert = "INSERT INTO Questionnaires_Table(BranchName,Factor,Region,Branch_ID,Current_Date,No_Employees) "
+ "SELECT BranchName,Factor,Region,Branch_ID,Current_Date,No_Employees "
+ "FROM Questionnaires_Table IN '" + dialog.FileName + "' Where Branch_ID = " + textBox1.Text ;
dbConnDest.Open();
OleDbDataAdapter dAdapter = new OleDbDataAdapter();
OleDbCommand cmd_insert = new OleDbCommand(query_insert, dbConnDest);
dAdapter.InsertCommand = cmd_insert;
textBox2.Text = query_insert.ToString();
dbConnDest.Close();
When I take the the content of query_insert in ms access, it works fine.
I think you need to use
cmd_insert.executeNonQuery()
Remove the comma after the last field name in the SELECT list.
"SELECT BranchName,Factor,Region,Branch_ID,Current_Date,No_Employees"
dAdapter.Update();
should do the trick
This seems suspect:
" Where Branch_ID = " + textBox1.Text ;
Does textBox1 contain a numeric ID? Does the ID that is entered exist in the source database?
I would 1) do a check that the ID exists and warn the user if it doesn't, and 2) change the query to use paramters instead of concatenating SQL.
What would happen if your company opened a branch with the ID of
"1; DROP TABLE Branches"