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.
Related
I want to connect to the tableau PostgreSQL server from my .Net framework to list all the reports and datasources published in the tableau server.
For doing this, I have done the following steps.
Added the npgsql.dll reference that i downloaded online
Added the below two namespaces in my class file
using NpgsqlTypes;
using Npgsql;
I added the connection sting as follows
I also tried with modifying the connection string with port value and renaming the DataSource to Server, Initial catalog to Database and provider Name to Npgsqll
My Method is as follows:
public DataTable getAllDataSourceNames()
{
DataTable dataSourceNames = new DataTable();
NpgsqlConnection conServer = new NpgsqlConnection(conString);
conServer.Open();
string command = #"select * from datasources";
NpgsqlDataAdapter sqlcmd = new NpgsqlDataAdapter(command,conServer);
sqlcmd.Fill(dataSourceNames);
return dataSourceNames;
}`
No error. I can build and run successfully the other links in the website. But cannot cannot establish connection to my postgresql server.
Any idea of how to establish the connection?
Working with Postgres Connection in c#:
private DataSet ds = new DataSet();
private DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
}
private void llOpenConnAndSelect_LinkClicked(object sender,
LinkLabelLinkClickedEventArgs e)
{
try
{
// PostgeSQL-style connection string
string connstring = String.Format("Server={0};Port={1};" +
"User Id={2};Password={3};Database={4};",
tbHost.Text, tbPort.Text, tbUser.Text,
tbPass.Text, tbDataBaseName.Text );
// Making connection with Npgsql provider
NpgsqlConnection conn = new NpgsqlConnection(connstring);
conn.Open();
// quite complex sql statement
string sql = "SELECT * FROM simple_table";
// data adapter making request from our connection
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
// i always reset DataSet before i do
// something with it.... i don't know why :-)
ds.Reset();
// filling DataSet with result from NpgsqlDataAdapter
da.Fill(ds);
// since it C# DataSet can handle multiple tables, we will select first
dt = ds.Tables[0];
// connect grid to DataTable
dataGridView1.DataSource = dt;
// since we only showing the result we don't need connection anymore
conn.Close();
}
catch (Exception msg)
{
// something went wrong, and you wanna know why
MessageBox.Show(msg.ToString());
throw;
}
}
The following link may help you: Using PostgreSQL in your C# .NET application
Short answer -- no, not sure what's wrong. Your code doesn't raise any alarm bells.
Somewhat related, and it may help: I'm a big fan of the Connection StringBuilder with Npgsql. Here is a brief example:
NpgsqlConnectionStringBuilder sb = new NpgsqlConnectionStringBuilder();
sb.ApplicationName = "Tableau " + Environment.GetEvironmentVariable("USERNAME");
sb.Host = "1.2.3.4";
sb.Port = 5432;
sb.Username = "foo";
sb.Password = "bar";
sb.Database = "postgres";
sb.Pooling = false;
sb.Timeout = 120;
conServer = new NpgsqlConnection(sb.ToString());
It demistifies all of this and makes injecting parameters easy. I highly recommend you add the ApplicationName property so that when you are monitoring sessions, you will know who is who.
I am trying to add a row to a table in a PostgreSQL database using ODBC. Although no exceptions are thrown, the row is not being added to the table. Here is my code:
void TestNewRow()
{
try
{
DataSet dataSet = new DataSet();
OdbcDataAdapter adapter = new OdbcDataAdapter();
adapter.SelectCommand =
new OdbcCommand("select read_time from plant_genie.plc_values_by_tag", m_db.GetConnection());
OdbcCommandBuilder builder =
new OdbcCommandBuilder(adapter);
adapter.Fill(dataSet);
DataTable valuesTable = dataSet.Tables[0];
DataRow newRow = valuesTable.NewRow();
newRow["read_time"] = DateTime.Now;
valuesTable.Rows.Add(newRow);
valuesTable.AcceptChanges();
dataSet.AcceptChanges();
adapter.Update(dataSet);
}
catch (Exception ex)
{
int a = 1;
}
}
I have a breakpoint in the exception handler and another at the end of the function. The second breakpoint is hit but not the first, so no exception is being thrown. I have triple-checked that I'm connecting to the correct database. I don't think I should need two AcceptChanges() calls and an Update() call, but even with all of that overkill, I'm still not getting a new row in my table. What am I doing wrong?
I tried to find a duplicate of this question, but there are so many questions about adding rows that if there was a duplicate, it is being hidden.
Thank you for your help.
RobR
Calling AcceptChanges marks all changes as accepted (i.e. it resets the state of everything to Unmodified), so no changes will be saved to the database. Remove this call to both the table and dataset and your changes should be saved.
I'm new to databases and I'm facing a roadblock. I'm getting an error when trying to update my database.
Also note that my database is SQL Server CE 4.0, if that helps.
private void Form1_Load(object sender, EventArgs e)
{
// Create a connection to the file datafile.sdf in the program folder
string dbfile = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + "\\userDtbs.sdf";
SqlCeConnection connection = new SqlCeConnection("datasource=" + dbfile);
// Read all rows from the table test_table into a dataset (note, the adapter automatically opens the connection)
SqlCeDataAdapter adapter = new SqlCeDataAdapter("SELECT * FROM history", connection);
DataSet data = new DataSet();
adapter.Fill(data);
// Add a row to the test_table (assume that table consists of a text column)
data.Tables[0].Rows.Add(new object[] { null, "Google", "http://www.google.com" });
// Save data back to the databasefile
adapter.Update(data);
// Close
connection.Close();
}
This code's outline is from another question's answer, and I'm trying to test it and get it to work properly. Thanks!
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.
The programs I am using are WAMP server (and its mysql feature in particular) and MS Visual Studio 2010 and I am programming in C#
Basically, here is what I need and can currently do with my application.
I have several datagridview's throughout the project and the first is simple, it loads all data from a specific table in the database at the push of a button. I have another form which I can insert records and have somehow managed to make a delete function which asks the user for 2 fields (first name and last name) and then it places these into a query and carries out the command.
What do I need to do?
I need to be able to implement some way for the form to update the database. I have chosen to do this through a datagridview control so the user can see what they are editting whilst they edit it.
I have the following code which I have tried to update the database based on the data in the datagridview control.
string connString = "server=localhost;User Id=root;database=collegelist;";
MySqlConnection conn = new MySqlConnection(connString);
string selectSQL = "SELECT * FROM collegeemployee";
conn.Open();
MySqlDataAdapter da = new MySqlDataAdapter(selectSQL, conn);
MySqlCommandBuilder builder = new MySqlCommandBuilder(da);
DataTable table = new DataTable();
try
{
dgView2.Rows.RemoveAt(dgView2.CurrentRow.Index);
da.Update(table);
}
catch (Exception exceptionObj)
{
MessageBox.Show(exceptionObj.Message.ToString());
}
the problem with this code (listed in a method obviously) is that while the grid is able to be modified, it is unable to pass the data back to the database.
Instead of updating your database with the empty table what you should do is.
i.Get the datasource . like
ii. Update/synchronize the data source and data adapter
Here is the code it should work, if it doesn't please comment and tell me the problem.
string connString = "server=localhost;User Id=root;database=collegelist;";
MySqlConnection conn = new MySqlConnection(connString);
string selectSQL = "SELECT * FROM collegeemployee";
conn.Open();
MySqlDataAdapter da = new MySqlDataAdapter(selectSQL, conn);
MySqlCommandBuilder builder = new MySqlCommandBuilder(da);
BindingSource BindingSourceToUpdate = (BindingSource)dgView2.DataSource; // because direct casting to data table was failing in VS2o1o
try
{
dgView2.Rows.RemoveAt(dgView2.CurrentRow.Index);
da.Update((DataTable)BindingSourceToUpdate.DataSource);
}
catch(exception)
{
}
conn.close();