I have a database with two tables; StudentID is the primary key on 'StudentList' table and StudentID is the foreign key on the 'JournalEntries' table.
On my website I have a search function so users can search for a student from the StudentList and the results are displayed in a datagrid. When the user selects a student from the list a journal entry box pops up. When they fill out the journal entry pop-up box and click the submit button I need the journal entry to be entered into the JournalEntries table tied to the student id that was selected from the datagrid.
protected void SearchGrid_SelectedIndexChanged(object sender, EventArgs e)
{
FNameLabel.Text = SearchGrid.SelectedRow.Cells[1].Text;
LNameLabel.Text = SearchGrid.SelectedRow.Cells[2].Text;
string constr = #"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=D:\Sites\Network2\nrsh\App_Data\myDB.mdb";
string cmdstr = "SELECT StudentID FROM StudentList WHERE = SearchGrid.SelectedRow.Cells[3].Text AND INSERT into JournalEntries (Topic, SubTopic, Summary, Date, Notes) values (#Topic, #SubTopic, #Summary, #Date, #Notes)";
OleDbConnection con = new OleDbConnection(constr);
OleDbCommand com = new OleDbCommand(cmdstr, con);
con.Open();
//The following fields are added from the journal entry form to the corresponding database fields
com.Parameters.AddWithValue("#Topic", ddlTopic.Text);
com.Parameters.AddWithValue("#SubTopic", txtSubTopic.Text);
com.Parameters.AddWithValue("#Date", txtDate.Text);
com.Parameters.AddWithValue("#Summary", txtSummary.Text);
com.Parameters.AddWithValue("#Notes", txtNotes.Text);
com.ExecuteNonQuery();
con.Close();
}
So that's my thought on the logic but it's probably completely wrong since I don't know much about sql. Any help would be great.
You cannot combine a SELECT and INSERT statement.
.......
string myValue = SearchGrid.SelectedRow.Cells[3].Text;
You don't have the value of SearchGrid.SelectedRow.Cells[3].Text in your string..you literally have "SearchGrid.SelectedRow.Cells[3].Text"...
string myValue = SearchGrid.SelectedRow.Cells[3].Text;
string cmdstr = "INSERT into JournalEntries (StudentID , Topic, SubTopic, Summary, Date, Notes) values (#StudentID , #Topic, #SubTopic, #Summary, #Date, #Notes)";
and the later
com.Parameters.AddWithValue("#StudentID", myValue);
com.Parameters.AddWithValue("#Topic", ddlTopic.Text);
com.Parameters.AddWithValue("#SubTopic", txtSubTopic.Text);
com.Parameters.AddWithValue("#Date", txtDate.Text);
com.Parameters.AddWithValue("#Summary", txtSummary.Text);
com.Parameters.AddWithValue("#Notes", txtNotes.Text);
I'm kinda guessing. You should give your table names and all the columns in your table and their datatypes (int, string, etc).
EDIT: REFACTOR.
You should create a class that accepts arguments. You should never have database code .... sitting where your GUI code is.
public class JournalEntriesManager
{
public static void InsertJournalEntry ( string studentID, string topic , string subTopic, DateTime DateOf , string summary , string notes )
{
// Your code here
}
}
That's like "Level 1" of "separation of concerns".
But in a nutshell, your GUI level code should COLLECT the information from the controls......and pass that info to BusinessLogic ("JournalEntriesManager" in this case).
Something like that.
You can't quite combine multiple statements with the AND statement, that is for combining multiple conditions together. Also, you can't just magically associate a row in one table to a row in another, instead, your JournalEntries table should have another column in it that contains the ID of the student that the entry is associated with. When you insert a new row into the JournalEntries table, you would include the student ID in that column and that is how your journal entries will be associated with a student.
Also, your queries can not include variable names like "SearchGrid.SelectedRow.Cells[3].Text", you would have to instead insert the value of that variable directly into the query text. Remember, you are sending this query to another server (your database server) and it has no idea what your variables are in your script.
Related
This is my first row where I create a track (THIS WORKS)
String TrackAdd = "INSERT INTO Track (Titel) VALUES (#Titel)";
using (SqlCommand sqlCmd = new SqlCommand(TrackAdd, connection))
{
sqlCmd.Parameters.AddWithValue("#Titel", textBoxTitel.Text);
sqlCmd.ExecuteNonQuery();
}
Then I want to use the ID which was just created for this Track, I need it so I can link it to something else (in this case a genre. I have specified the names for genres in a different table and need their IDs)
I'm now trying this but its not working and I don't really know what to do.
using (var connection = Database.connection)
{
String Track1Genre = "INSERT INTO TrackGenre (TrackId, GenreId) VALUES (#TrackId, #GenreId)";
string Genre = listBoxGenre.GetItemText(listBoxGenre.SelectedItem);
using (SqlCommand sqlCmd = new SqlCommand(Track1Genre, connection))
{
sqlCmd.Parameters.AddWithValue("#TrackId", "Select Id from Track WHERE Titel = textBoxTitel.Text");
sqlCmd.Parameters.AddWithValue("#GenreId", "Select Id from Genre where Genre = Genre");
sqlCmd.ExecuteNonQuery();
}
}
NOTE: There's nothing wrong with the connection or anything, I just need help how to get the ID's out of the database and insert them into a different table
Two ways to do it:
Output Inserted.Id
INSERT INTO Track (Titel) VALUES output INSERTED.ID (#Titel)
and in C#, use:
int lastId =(int)cmd.ExecuteScalar();
Identity_Insert On
SET IDENTITY_INSERT dbo.Track ON;
INSERT INTO Track (Id, Titel) VALUES (1, #Titel)
SET IDENTITY_INSERT dbo.Track OFF;
In this method you already know what Id you are inserting so you can just use this to update your TrackGenre table. But, yes, you have to track your Ids or may be before executing check for last id using select max(id) from Track
You're close. You can't inject SQL the way you intended. You have to move that your insert statement so the query will do a select for each value based on your parameters.
Let's try to workout what the SQL query that gets executed will look like, when you start with this:
String Track1Genre = "INSERT INTO TrackGenre (TrackId, GenreId) VALUES (#TrackId, #GenreId)";
sqlCmd.Parameters.AddWithValue("#TrackId", "Select Id from Track WHERE Titel = textBoxTitel.Text");
sqlCmd.Parameters.AddWithValue("#GenreId", "Select Id from Genre where Genre = Genre");
Remember that whatever (string) value is set on a parameter will be used, without any evaluation. So the above statement will lead to this sql being executed:
INSERT INTO TrackGenre (TrackId, GenreId)
VALUES ('Select Id from Track WHERE Titel = textBoxTitel.Text',
'Select Id from Genre where Genre = Genre');
So it nicely did prevent a SqlInjection attack but it didn't return Id's to tables Track and Genre either, in fact it would bark about a conversion failed to data type int.
Instead you can pass the selection parameters as is and then use those in the queries to get the id's of the rows you're interested in.
Staying as close as possible to what you currently have, this would work:
using (var connection = Database.connection)
{
String Track1Genre = #"
INSERT
INTO TrackGenre(TrackId, GenreId)
VALUES (
(SELECT id FROM track WHERE titel = #titel), /* do a select for the ID */
(SELECT id FROM genre WHERE genre = #genre))";
string Genre = listBoxGenre.GetItemText(listBoxGenre.SelectedItem);
using (SqlCommand sqlCmd = new SqlCommand(Track1Genre, connection))
{
// caution, better use Add, see the note
sqlCmd.Parameters.AddWithValue("#titel", textBoxTitel.Text);
sqlCmd.Parameters.AddWithValue("#Genre", Genre);
sqlCmd.ExecuteNonQuery();
}
}
Keep in mind that the insert statement will fail if you have tracks with the same title, or genre's with same name. But that is up to you to handle or prevent from happening upstream.
If you want to be 100% sure that the Id you get from the insert of Track, refer to the Output Inserted.Id option in the answer of Sunil. You'll have to bring the lastid variable over to the code I've shown here, replacing the first parameter with it (and adapt the insert query accordingly).
Note
There is a potential issue with the use of AddWithValue as explained in this blogpost from JCoohorn: https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
It is better to prevent the SqlParameter class guess your type wrong. Consider to use
sqlCmd.Parameters.Add("#titel", SqlDbType.NVarChar, 250).Value = textBoxTitel.Text;
instead.
If you want to experiment with the insert query first to get the feel what it is doing, fork this SEDE query.
I dont know if it is a typo or genuine mistake which should be corrected
this line from your code
sqlCmd.Parameters.AddWithValue("#TrackId", "Select Id from Track WHERE Titel = textBoxTitel.Text");
should be written like this
sqlCmd.Parameters.AddWithValue("#TrackId", "Select Id from Track WHERE Titel = " + textBoxTitel.Text);
same problem is with Genre tooo. if your code written is correct then your query is actually searching for 'textBoxTitel.Text' instead of trackid
I have the following situation:
In my database, I have a table called Person. A person has an ID. In my conceptual model, student is inherited from person, so I have another table called Student.
I wrote C# code to insert into the Student table:
string query = "INSERT INTO Person (ID, ...) VALUES("id",...);";
MySqlCommand command = new MySqlCommand(query, connection);
command.ExecuteNonQuery();
query = "INSERT INTO Student (..., ID) VALUES(...,"id");";
command.ExecuteNonQuery();
Obviously, I need to add values into the Person class first, because every student is a person. So, after I did that, I try to add the rest of the Student data into the table.
The problem is that I am getting this error:
Duplicate entry (id) for key "PRIMARY"
which I don't understand, since this key needs to be the same.
The exception message is pretty clear:
Duplicate entry (id) for key "PRIMARY"
You ARE duplicating the ID on a table.
You didn't tell in which line this is happening, so, let's assume both possibilities (and that the error is not elsewhere).
The exception is happening when you are trying to insert into table PERSON.
In this case,if the PRIMARY KEY of this table was AUTO INCREMENT, this wouldn't be possible. If it isn't, and you are inserting the ID of the record by yourself, your code is not creating the ID's correctly and is inserting a value that already exists in the table.
To check if this is the case during runtime, just make a select for the ID you are trying to insert BEFORE actually inserting it:
string query = "SELECT count(*) FROM Person WHERE ID = " + id;
MySqlCommand command = new MySqlCommand(query, connection);
int count = (int)command.ExecuteScalar();
if (count > 0)
{
//You already inserted this ID. Warn the user
}
You are getting the exception on when inserting into table STUDENT
First, lets assume that the ID you are inserting into STUDENT that you're showing here is not the PRIMARY KEY of the table student, but only a FK (foreign key) to table PERSON.
In this case, the same fro the item 1 applies here. You ARE entering a duplicate id in the table. Use the same approach from item 1 to verify this.
But if the ID from PERSON is really the same ID from STUDENT (a ONE to ONE relationship), what's the problem?
Exactly the same. You are entering a duplicated ID.
So, no matter where the error is happening, you are allowing your code to try to insert a DUPLICATE ID (primary key) in the table.
Again, you must be creating the ID's manually, as an auto-increment primary key would not cause this problem (UNLESS you are manually setting the ID, in which case MySQL would use this value instead of the automatic value).
If you are creating the ID's manually, you MUST ensure that they are not duplicates.
I don't even know if this should be called an answer or a hack, but it worked:
string query = "INSERT INTO Person (ID, ...) VALUES(id, ...);
INSERT INTO Student (..., ID) VALUES(..., (select ID from Person WHERE Person.ID = id));";
MySqlCommand command = new MySqlCommand(query, connection);
I have a Windows Presentation Foundation, I have a Database called "Worker" and a table that belongs to this Database, the table is called TestTable,with 6 columns: Id,Name, Lastname, Gender, Email and Password, I already added some elements,in the Mainwindow the user can see all the information contained in the database columns except Id, I kept Id out of user`s sight, so I have different Listboxs with the information: ListboxNames, ListboxLastnames, ListboxGenders, etc...I made a method that allows me to delete rows from the Database according to the ListboxNames.SelectedItem, but it deletes using the name, which is not convenient because there could be several equal names, could you explain me how to get the correct id according to the ListboxNames.SelectedItem, how could I delete using the Id selecting a name from the ListBox?? Remember I never show the Id to the usser, thanks beforehand!!!
This is the method I use to delete, I guess I need to get the ids with the same name from the database maybe first and then I must choose between the ids the correct one, you just let me know!
private void buttonDelete_Click(object sender, RoutedEventArgs e)
{
cmd.CommandText = "delete from TestTable where name='" + listBoxListNames.SelectedItem + "'";
con.Open();
cmd.ExecuteNonQuery();
con.Close();
listBoxListNames.Items.Clear();
listBoxListLastnames.Items.Clear();
listBoxListGenders.Items.Clear();
listBoxListEmails.Items.Clear();
listBoxListPasswords.Items.Clear();
ShowDatabase();
}
You can use SelectedValue property of listbox in this case; for that you need to bind the list box in following way:
Listbox definition:
<ListBox Name="myList" SelectedValuePath="myID" DisplayMemberPath="myTextField"... />
Binding:
DataTable myDataTable= getDataTable();//populate datatable from database
myList.SelectedValuePath = "myID";
myList.DisplayMemberPath = "myTextField";
myList.ItemsSource = myDataTable;
Then you can re-write your code to delete items using SelectedValue :
private void buttonDelete_Click(object sender, RoutedEventArgs e)
{
cmd.CommandText = "delete from TestTable where itemID=#myID";
cmd.Parameters.AddWithValue("myID", myList.SelectedValue);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
//Do rest of operations here
}
Note : You have to use parameterized query to avoid injection; so take a look into the query too
I have the following method:
Connection c =new Connection();
SqlCommand cmd = new SqlCommand();
String empID = toolStripTextBox1.Text;
cmd.CommandText = "DELETE FROM tblEmployee WHERE employeeNumber='empID'";
cmd.Connection = c.con;
c.con.Open();
dataGridView1.CurrentCell = null;
int numberDeleted = cmd.ExecuteNonQuery();
MessageBox.Show(numberDeleted.ToString() + " employees were deleted.<br>");
c.con.Close();
I'm trying to delete a record in the table and update gridview to show the remaining records in the table. the code doesn't delete any record
This:
DELETE FROM tblEmployee WHERE employeeNumber='empID'
Should be converted to use a parametrized query in the following way:
cmd.CommandText="DELETE FROM tblEmployee WHERE employeeNumber=#id";
The reason is that your previous statement was simply concatenating the delete from ... part with the string 'empid' which I assume is not what you want. You are after something like this:
delete from ... where employeeNumber={some_number} where some_number is a parameter
In order to pass a parameter to your SQL Statement you do this:
cmd.Parameters.AddWithValue("#id",empID);//I assume empID is a variable containing an ID
cmd.ExecuteNonQuery();
If you want the change immediately reflected on your grid, you need to select the data again and rebind your grid.
The problem is that probably no empID with the value 'empID' exists..
You didn't put the value of the empID in the command, but added an exact string of 'empID', which cannot be found in your table.
Put the empID value as a parameter like Icarus advised.
I have a winform which i have attached here.. When i Insert record in Customer table, I also want to add the record in the orderlineitems table in my database as of which the record in the Order table will also be inserted.
I have inserted the record in Customer table but when i insert record in OrderLineItems table, it shows an error.
I also wanted to ask that, my OrderLineItems Table in database contains columns as :
ID(pk)
OrderID(pk)
Quantity
Particular
Rates
Status
On my Form, I have only quantity, particular and rates fields from which i can get their values but i dont have Status and Orderid values on my winform. how do i get the values of status and orderId then?
My Code is:
private void buttonInsert_Click(object sender, EventArgs e)
{
string SQL = String.Format("Insert into Customer values ('{0}','{1}','{2}')", textBoxName.Text, textBoxContactNo.Text, textBoxAddress.Text);
//string SQL1 = String.Format("Insert into Order values ({0},'{1}','{2}',{3})",);
DataManagementClass dm = new DataManagementClass();
int result = dm.ExecuteActionQuery(SQL);
if (result > 0)
{
for (int i = 0; i < recordsDataGridView.RowCount ; i++)
{
string query = String.Format("Insert into OrderLineItems values({0},'{1}','{2}','{3}',{4})",7,QuantityColumn, ParticularColumn, RatesColumn,1);
dm.ExecuteActionQuery(query);
}
//string query = String.Format("Insert into OrderLineItems values ('{0}','{1},'{2}'
}
What am i doing wrong here. please guide me the correct way.
Thanx..
Suggest a few enhancements to get your business logic working and maintainable:
write a stored procedure for your CreateCustomer and CreateLineItem routines in your database.
use a SqlCommand and its Parameters collection. Stop whatever you're doing right now and guard against SQL injection.
remove all this code from the button click event.
create new methods like CreateCustomer and CreateLineItems. Call these method from your button click handler method.
private void buttonInsert_Click(object sender, EventArgs e)
{
int result = CreateCustomer(textBoxName.Text.Trim(),
textBoxContactNo.Text.Trim(),
textBoxAddress.Text.Trim());
if (result > 0)
{
foreach(var row in recordsDataGridView.Rows)
{
CreateLineItem(quantity, particulars, rates);
}
}
You are inserting values like this: '{1}','{2}','{3}'
This leads me to assume you are inserting string values.
If there is an apostroph in your string values, it will cause a syntax error.
Try
yourstring.replace("'", "''")
on the arguments.
Also, do as p.campbell suggest..
Use parameters to prevent SQL injection..
Somebody might malicously take advantage of your code's open security holes..