I've been squeezing my mind trying to figure out why my code isn't working.
I am trying to read from a DataSet that filled with data from access database and insert the data into an Oracle database which is created previously.
When I try the following code it won't work and although I use the try and catch block, when debugging it would freeze and won't show me any error.
if can see that I have commented out the block just right above my foreach loop..which works perfectly, Any help from you is so much appreciated :
private void button3_Click(object sender, EventArgs e)
{
string query1 = "Select * from Test;";
string StrQuery= "Insert Into TEST (ID, DATA) Values (:ID, :DATA)";
Conn = new OleDbConnection(connStr);
Conn.Open();
using (OleDbConnection connection1 = new OleDbConnection(connStr))
{
using (OleDbDataAdapter adapter1 = new OleDbDataAdapter(query1, connection1))
{
DataSet ds1 = new DataSet();
adapter1.Fill(ds1);
// no need for refilling DataGridView1.DataSource = ds.Tables[0]
// insterting the dataset into oracle
try
{
using (OracleConnection connect = new OracleConnection(oradb1))
{
connect.Open();
using (OracleCommand comma = new OracleCommand(StrQuery, connect))
{
/*comma.Parameters.Add(new OracleParameter(":ID", 2));
comma.Parameters.Add(new OracleParameter(":DATA", 2));
comma.ExecuteNonQuery();*/
foreach (DataRow drRow in ds1.Tables[0].Rows)
{
for (int i = 0; i < ds1.Tables[0].Columns.Count; i++)
{
comma.Parameters.Add(new OracleParameter(":ID", drRow[i]));
comma.Parameters.Add(new OracleParameter(":DATA", drRow[i]));
comma.ExecuteNonQuery();
}
}
connect.Close();
connect.Dispose();
}
}
}
catch (OracleException)
{
System.Diagnostics.Debugger.Break();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Conn.Close();
}
You are looping columns but adding the drRow[i] as values in the parameters.
I do not think this is what you intended.
skip the columns loop and add the first column value to id and second column value to data.
that should be what you wanted.... if not then describe a bit more...
Expanding on Judgemaik's answer, I believe you need to do something like this instead (can't really tell what the names of the columns in your access table are but you get the idea:
foreach (DataRow drRow in ds1.Tables[0].Rows)
{
comma.Parameters.Add(new OracleParameter(":ID", drRow["IDColumnFromAccessDB"]));
comma.Parameters.Add(new OracleParameter(":DATA", drRow["DATAColumnFromAccessDB"]));
comma.ExecuteNonQuery();
}
A similar approach is outlined in my answer here. In that particular case I was moving data from SQL Server Compact into Access, but the same idea could very well be used to move data between any two OleDb data sources.
It uses an OleDbDataAdapter to pull the source table into a DataTable, copies it over to another DataTable, and then uses another OleDbDataAdapter to update the corresponding table in the destination database.
Related
I am trying to update 2 columns in an Oracle database using C#. The columns I want to update are StartTime i.e. a timestamp and Name i.e. string. However when I run my code, the application freezes. I following is my code:
public int StartProduction(string serialNr, string empName)
{
string queryString = "UPDATE RO_EXEMPLAAR_PIM SET PLAKTAFEL_START=systimestamp, STARTED_BY=:startedBy WHERE SERIENR=:serialNr";
using (OracleConnection connection = new OracleConnection(connectionString))
{
using (OracleCommand command = new OracleCommand(queryString, connection))
{
try
{
OracleDataAdapter da = new OracleDataAdapter();
connection.Open();
command.Parameters.AddWithValue("serialNr", serialNr);
command.Parameters.AddWithValue("startedBy", empName);
da.InsertCommand = command;
int nrOfRecordsChanged = command.ExecuteNonQuery();
return nrOfRecordsChanged;
}
catch
{
return -1; //which means the try-block was not executed succesfully
}
finally
{
connection.Close();
}
}
}
}
I call it in a form as this:
if (dh.StartProduction(serialNr, empName) != -1)
{
MessageBox.Show("Production started successfully!");
}
else
{
MessageBox.Show("Production cannot be started!");
}
I looked up online and could not find what is wrong with my code. Thanks in advance!
Try a non locking read query like;
SELECT * FROM V$VERSION;
If that works (proving your connection string works).
Then you probably have a locking issue.
In general: (especially for devs)
Make sure you are not missing a "commit;" in your sql-developer or dbvisualizer or something like that. (or somebody on your dev team).
Running an update without a "commit;" in side these tools will lock a row.
If you can't find the culprit : a reboot of the server is in order.
i have a list of String Data i would Like to Store in my MySQL database Table in Column "Categories".
Is there a way to store it at a go because its a long list.`
public Class PickerView{
List<string> CategoriesPicker = new List<string>();
public Button SaveItemsButton = new Button();
public PickerView()
{
CategoriesPicker.Items.Add("Hotels & Travel");
CategoriesPicker.Items.Add("Restaurant");
CategoriesPicker.Items.Add("Wholesalers");
CategoriesPicker.Items.Add("Automotives");
CategoriesPicker.Items.Add("Pets");
CategoriesPicker.Items.Add("Musical Instruments Services");
CategoriesPicker.Items.Add("Specialty Food");
CategoriesPicker.Items.Add("Food");
CategoriesPicker.Items.Add("Boutique");
CategoriesPicker.Items.Add("Home & Gardens");
CategoriesPicker.Items.Add("Shopping");
CategoriesPicker.Items.Add("Education");
CategoriesPicker.Items.Add("Books,Mags,Music & Video");
CategoriesPicker.Items.Add("Fashion");
CategoriesPicker.Items.Add("Event Planning & Services");
CategoriesPicker.Items.Add("Arts & Craft");
CategoriesPicker.Items.Add("Local Services");
CategoriesPicker.Items.Add("NightLife(Bars..)");
SaveItemsButton.Clicked += SavedItemsButton_Clicked
}
private void SavedItemsButton_Clicked(object sender, System.EventArgs e)
{
string sqlstring = "server=; port= ; user id =;Password= ;Database=test;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "INSERT INTO test.maintable (Categories)values('" +(**//I DONT KNOW WHAT TO WRITE HERE TO SAVE ALL AT ONCE**) + "');";
MySqlCommand cmd = new MySqlCommand(Query, conn);
cmd.ExecuteReader();
conn.Close();
}
}`
How do i save the list of items in CategoriesPicker in database when SaveItemsButton is clicked.
Simple use the mysql insert into statement.
insert into tbl1 values
(1, 'Name1', 1, null),
(2, 'Name2', 2, null),
(3, 'Name3', 1, null);
(3, 'Name3', 1, null) is of course the structure of tbl1
This will work in any language you use or even in comand line
MySQL (and MariaDB) don't have list-valued column types since that goes against first normal form in database design.
What you do instead is what #nbk suggested and, using whatever database framework you chose, insert multiple rows. Here's a sample table definition for MariaDB/MySQL if you don't have one already:
Microsoft's current recommended way of interacting with a database is Entity Framework Core. The documentation there can help you with connecting to a database, creating a table, adding rows to a table and saving all of that to the database.
Hope that helps!
I added using blocks to your code to ensure that your database objects are closed and disposed even if there is an error.
Set the query text only once, it stays the same for each iteration of the loop. Likewise the parameter is added outside the loop. Only the value of the parameter is changed inside the loop. We use .ExecuteNonQuery (not reader) for Insert, Update or Delete. .ExecuteReader is used for returning data.
private List<string> CategoriesPicker = new List<string>();
//add all the items to the list
private void SavedItemsButton_Clicked(object sender, System.EventArgs e)
{
string sqlstring = "server=; port= ; user id =;Password= ;Database=test;";
using (MySqlConnection conn = new MySqlConnection(sqlstring))
{
string Query = "INSERT INTO test.maintable (Categories)values(#Category);";
using (MySqlCommand cmd = new MySqlCommand(Query, conn))
{
cmd.Parameters.Add("#Category", MySqlDbType.VarChar);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
foreach (String item in CategoriesPicker)
{
cmd.Parameters["#Category"].Value = item;
cmd.ExecuteNonQuery();
}
}
}
}
I've been working on a small project and came to an issue with a SQL Server database. The SQL Server database works fine when connecting and reading from it. There are no issues when it comes to the variables, they all update fine.
However, the database itself does not update at all. I believe it is the da.Update that is going wrong, but I've never worked with SQL before so I can't find what is wrong with it.
What it should do:
Read data from the SQL Server table
Put it in a DataTable
Take changes from a list and put them into the DataTable
Add the changes to the database
What it does do:
Reads the data from the SQL Server table
Puts it in a DataTable
Takes changes from a list and puts them into the DataTable
Doesn't update the database, but does not fail the try and catch
Code:
public void PushToDatabase()
{
// Get update from list
PropertiesList[0] = Name;
PropertiesList[1] = Token;
PropertiesList[2] = ClientID;
PropertiesList[3] = ClientInfo;
PropertiesList[4] = Owner;
PropertiesList[5] = OtherID;
PropertiesList[6] = Prefix;
PropertiesList[7] = ApiKey;
// Connect to the database
using (var connection = new SqlConnection(connectionString))
using (SqlDataAdapter da = new SqlDataAdapter("SELECT ID, Name, Token, ClientID, ClientInfo, Owner, OtherID, Prefix, GoogleApi FROM dt", connection))
{
SqlCommandBuilder cb = new SqlCommandBuilder(da);
connection.Open();
DataTable dt = new DataTable();
// Load then modify the data
da.Fill(dt);
dt.Rows[0].BeginEdit();
dt.Rows[0][1] = PropertiesList[0];
dt.Rows[0][2] = PropertiesList[1];
dt.Rows[0][3] = PropertiesList[2];
dt.Rows[0][4] = PropertiesList[3];
dt.Rows[0][5] = PropertiesList[4];
dt.Rows[0][6] = PropertiesList[5];
dt.Rows[0][7] = PropertiesList[6];
dt.Rows[0][8] = PropertiesList[7];
dt.Rows[0].EndEdit();
// Put the data back
try
{
da.AcceptChangesDuringUpdate = true;
da.DeleteCommand = cb.GetDeleteCommand(true);
da.UpdateCommand = cb.GetUpdateCommand(true);
da.InsertCommand = cb.GetInsertCommand(true);
dt.AcceptChanges();
da.Update(dt);
MessageBox.Show("Properties Updated", "Update"); //this completes fine and displays the updated message
}
catch
{
MessageBox.Show("Cant Store data", "Error");
}
connection.Close();
}
}
Sorry about the messy code I've been adding things in to try to fix this but I have not had any success.
You shouldn't be calling AcceptChanges before the Update, so you need to remove dt.AcceptChanges();
A longer answer is that the AcceptChanges will mark all the added and updated rows as now being unmodified, and it will permanently delete the rows you've asked to be deleted (from the datatable -- not the table in Sql Server). Then when you call Update, it scans the databable looking for any rows that are in "Added", "Modified" or "Deleted" status, and finds there are none (because you just changed them all to "Unmodified" via AcceptChanges), so nothing is sent to the database.
below is the code I wrote to fill dropdown list from the database,and I am not getting where I did mistake..help me in finding out and correcting my mistake.
void filldistrict()
{
DropDownList4.Items.Clear();
DropDownList4.Items.Add("--District--");
String q="select * from DLIST";
SqlCommand cmd=new SqlCommand(q,cn);
SqlDataReader rec = cmd.ExecuteReader();
if (rec.Read())
DropDownList4.Items.Add(rec.getValue(1).ToString);
rec.Close();
}
Your code is very close - the only problem is this line:
if (rec.Read())
You can also use new ListItem() when adding to the Items collection. You can use the overload that takes two strings that will set the text and the value, as well.
That will only get the first row of the returned records, not all of them. What you want is to loop through the records in rec, like this:
void filldistrict()
{
DropDownList4.Items.Clear();
DropDownList4.Items.Add("--District--");
String q="select * from DLIST";
SqlCommand cmd=new SqlCommand(q,cn);
using (SqlDataReader rec = cmd.ExectueReader())
{
while (rec.Read())
{
DropDownList4.Items.Add(new ListItem(rec.GetValue(1).ToString()));
}
}
}
Note that I used a using block with the reader so its automatically closed while the block is exited. I would also suggest doing the same with your SqlConnection.
The alternative provided by Ali is also a valid approach.
SqlConnection sql_cnt=new SqlConnection("connectionString");
SqlCommand sql_cmd=new SqlCommand("select * from DLIST",sql_cnt);
Dataset dt_data=new Dataset();
SqlDataAdapter sql_adp=new SqlDataAdapter(cmd);
try
{
sql_cnt.Open();
sql_adp.Fill(dt_data);
sql_cnt.Close();
}
catch(Exception err)
{
//Do something;
}
DropDownList4.ValueMember="the name of the field which you want to be shown in dropdown list";
DropDownList4.DataSource=dt_data;
I'm currently creating a small application using Windows Forms and SQLite. After reading some tutorials I implemented this method for data retrieval:
public DataTable GetDataTable(ref SQLiteDataAdapter adapter, string sql)
{
DataTable dt = new DataTable();
// Connect to database.
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
// Create database adapter using specified query
using (adapter = new SQLiteDataAdapter(sql, connection))
// Create command builder to generate SQL update, insert and delete commands
using (SQLiteCommandBuilder command = new SQLiteCommandBuilder(adapter))
{
// Populate datatable to return, using the database adapter
adapter.Fill(dt);
}
return dt;
}
(As well as another GetDataTable which doesn't take an SQLiteDataAdapter as parameter)
I have three classes, let's call them UI, Link and Database. The UI does nothing but displaying the data and raising events upon user interaction. The Link creates the Database and a SQLiteDataAdapter, retrieves a data table through the method mentioned above, and binds it to a data grid view on the UI. The user cannot alter the table through the data grid view, but should do so through some text boxes. (does this make binding the table to the dgv obosolete?)
What's the best way to get the user input from the text boxes to the database, using the adapter? Or should I use DataReader and some Insert method instead of an adapter?
As of know, the UI exposes its controls through Get-methods. Is there a better solution?
private void Initialize()
{
// Subscribe to userInterface events
userInterface.DataGridViewSelectionChanged += new EventHandler(userInterface_DataGridViewSelectionChanged);
userInterface.NewClicked += new EventHandler(userInterface_NewClicked);
userInterface.SaveClicked += new EventHandler(userInterface_SaveClicked);
// Get dataGridView from userInterface and bind to database
bindingSource = new BindingSource();
bindingSource.DataSource = database.GetDataTable(ref adapter, "SELECT * FROM SomeTable");
userInterface.GetDataGridView().DataSource = bindingSource;
}
void userInterface_DataGridViewSelectionChanged(object sender, EventArgs e)
{
if (userInterface.GetDataGridView().SelectedRows.Count != 0)
{
DataGridViewRow row = userInterface.GetDataGridView().SelectedRows[0];
userInterface.GetIDTextBox().Text = row.Cells["PrimaryKey].Value.ToString();
userInterface.GetOtherIDTextBox().Text = row.Cells["ForeignKey"].Value.ToString();
DataTable dt = database.GetDataTable("SELECT * from SomeTable WHERE ForeignKey=" + row.Cells["ForeignKey"].Value);
userInterface.GetLastNameTextBox().Text = dt.Rows[0]["LastName"].ToString();
userInterface.GetFirstNameTextBox().Text = dt.Rows[0]["FirstName"].ToString();
userInterface.GetCompanyTextBox().Text = dt.Rows[0]["Company"].ToString();
}
}
void userInterface_NewClicked(object sender, EventArgs e)
{
// Get all text boxes and clear them
// Let the UI take care of this by itself?
}
void userInterface_SaveClicked(object sender, EventArgs e)
{
// Get text/data from all text boxes and insert (or update if editing table) into database
// adapter.Update(...)?
}
Cheers!
INSERT, UPDATE and DELETE operations are the working of a DbCommand. You need a different method that takes the sql string and a collection of SQLiteParameter that you use for the INSERT.
I will try to write some pseudocode for the INSERT operation
public class MyHelperClass
{
public static int InsertCommand(string sql, SQLiteParameter[] parameters)
{
int result = 0;
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
using (SQLiteCommand cmd = new SQLiteCommand(sql, connection))
{
cmd.Parameters.AddRange(parameters);
result = cmd.ExecuteNonQuery();
}
return result;
}
}
Now you have to build the parameter array to pass to the help method and this should be done from your UI code
string sqlCommand = "INSERT INTO table1 (FirstName, LastName) VALUES (#fName, #lName)";
SQLiteParameter[] p = new SQLiteParameter[2];
p[0] = new SQLiteParameter("#fName", TextBox1.Text);
p[1] = new SQLiteParameter("#lName", TextBox2.Text);
int rowAdded = MyHelperClass,InsertCommand(sql, p);
The operation for the UPDATE and DELETE command are similar. Also I suggest you to add a version of your GetDataTable that accepts a parameter array instead of building sql commands with string concatenation. As repetead innumerable times here string concatenation leads to errors and, worst of all, to weak code easily exposed to sql injection.