My project that I am working on is almost finished. I am loading a .MDB file, displaying the contents on a DataGrid and attempting to get those changes on the DataGrid and save them back into the .MDB file. I am also going to create a function that allows me to take the tables from one .MDB file and save it to another .MDB file. Of course, I cannot do any of this if I cannot figure out how to save the changes back to the .MDB file.
I have researched Google extensively and there are no answers to my question. I consider myself a beginner at this specific topic so please don't make the answers too complicated -- I need the simplest way to edit a .MDB file! Please provide programming examples.
- Assume that I've already made a connection to a DataGrid. How do I get the changes made by the Datagrid? Im sure this one is simple enough to answer.
- I then need to know how to take this Datatable, insert it into Dataset it came from then take that Dataset and rewrite the .MDB file. (If there is a way of only inserting the tables that were changed I would prefer that.)
Thank you in advance, let me know if you need more information. This is the last thing I am probably going to have to ask about this topic...thank god.
EDIT:
The .mdb I am working with is a Microsoft Access Database. ( I didnt even know there were multiple .mdb files)
I know I cannot write directly to the .MDB file via a streamwriter or anything but is there a way I can possibly generated a .MDB File with the DataSet information already in it? OR is there just a way that I can add tables to a .MDB file that i've already loaded into the DataGrid. There HAS to be a way!
Again, I need a way to do this PROGRAMMATICALLY in C#.
EDIT:
Okay, my project is fairly large but I use a seperate class file to handle all Database connections. I know my design and source is really sloppy, but it gets the job done. I am only as good as the examples I find on the internet.
Remember, I am simply connecting to a DataGrid in another form. Let me know if you want my code from the Datagrid form (I dont know why you would need it though). DatabaseHandling.cs handles 2 .MDB files. So you will see two datasets in there. I will use this eventually to take tables from one Dataset and put them into another Dataset. I just need to figure out how to save these values BACK into a .MDB file.
Is there anyway to do this? There has to be a way...
EDIT:
From what i've researched and read...I think the answer is right under my nose. Using the "Update()" command. Now while this is re-assuring that there is infact a simple way of doing this, I am still left with the problem that I have no-friggin-clue how to use this update command.
Perhaps I can set it up like this:
Oledb.OledbConnection cn = new Oledb.OledbConnection();
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Staff.mdb";
Oledb.OledbCommand cmd = new Oledb.OledbCommand(cn);
cmd.CommandText = "INSERT INTO Customers (FirstName, LastName) VALUES (@FirstName, @LastName)";
I think that may do it, but I dont want to manually insert anything. I want to do both of these instead:
- Take information that is changed on the Datagrid and update the Access Database File (.mdb) that I got it from
- Create a function that allows me to take tables from another Access Database File (.mdb) and replace them in a secondary Access Database file (.mdb). Both files will use the exact same structure but will have different information in them.
I hope someone comes up with a answer for this...my project is done all that awaits is one simple answer.
Thank you again in advance.
EDIT:
Okay...good news. I have figured out how to query the .mdb file itself (I think). Here is the code, which doesn't work because I get a runtime error due to the sql command i'm attempting to use. Which will bring me to my next question.
New function code added to DatabaseHandling.cs:
static public void performSynchronization(string table, string tableTwoLocation)
{
OleDbCommand cmdCopyTables = new OleDbCommand("INSERT INTO" + table + "SELECT * FROM [MS Access;" + tableTwoLocation + ";].[" + table + "]"); // This query generates runtime error
cmdCopyTables.Connection = dataconnectionA;
dataconnectionA.Open();
cmdCopyTables.ExecuteNonQuery();
dataconnectionA.Close();
}
As you can see, I've actually managed to execute a query on the connection itself, which I believe to be the actual Access .MDB file. As I said though, the SQL query I've executed on the file doesn't work and generated a run-time error when used.
The command I am attempting to execute is supposed to take a table from a .MDB file and overwrite a table of the same type of a different .MDB file. The SQL command I attempted above tried to directly take a table from a .mdb file, and directly put it in another -- this isn't what I want to do. I want to take all the information from the .MDB file -- put the tables into a Datatable and then add all the Datatables to a Dataset (which i've done.) I want to do this for two .MDB files. Once I have two Datasets I want to take specific tables out of each Dataset and add them to each file like this:
- DataSetA >>>>----- [Add Tables (Overwrite Them)] ----->>>> DataSetB
- DataSetB >>>>----- [Add Tables (Overwrite Them)] ----->>>> DataSetA
I want to take those each those Datasets and then put them BACK into each Access .MDB file they came from. Essentially keeping both databases synchronized.
So my questions, revised, is:
- How do I create a SQL query that will add a table to the .MDB file by overwriting the existing one of the same name. The query should be able to be created dynamically during runtime with an array that replaces a variable with the table name I want to add.
- How do I get the changes that were made by the Datagrid to the DataTable and put them back into a DataTable (or DataSet) so I can send them to the .MDB file?
I've tried to elaborate as much as possible...because I believe I am not explaing my issue very well. Now this question has grown wayyy too long. I just wish I could explain this better. :[
EDIT:
Thanks to a user below I think I've almost found a fix -- the keyword almost. Here is my updated DatabaseHandling.cs code below. I get a runtime error "Datatype Mismatch." I dont know how that could be possible considering I am trying to copy these tables into another database with the exact same setup.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.IO;
namespace LCR_ShepherdStaffupdater_1._0
{
public class DatabaseHandling
{
static DataTable datatableB = new DataTable();
static DataTable datatableA = new DataTable();
public static DataSet datasetA = new DataSet();
public static DataSet datasetB = new DataSet();
static OleDbDataAdapter adapterA = new OleDbDataAdapter();
static OleDbDataAdapter adapterB = new OleDbDataAdapter();
static string connectionstringA = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationA();
static string connectionstringB = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationB();
static OleDbConnection dataconnectionB = new OleDbConnection(connectionstringB);
static OleDbConnection dataconnectionA = new OleDbConnection(connectionstringA);
static DataTable tableListA;
static DataTable tableListB;
static public void addTableA(string table, bool addtoDataSet)
{
dataconnectionA.Open();
datatableA = new DataTable(table);
try
{
OleDbCommand commandselectA = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionA);
adapterA.SelectCommand = commandselectA;
adapterA.Fill(datatableA);
}
catch
{
Logging.updateLog("Error: Tried to get " + table + " from DataSetA. Table doesn't exist!");
}
if (addtoDataSet == true)
{
datasetA.Tables.Add(datatableA);
Logging.updateLog("Added DataTableA: " + datatableA.TableName.ToString() + " Successfully!");
}
dataconnectionA.Close();
}
static public void addTableB(string table, bool addtoDataSet)
{
dataconnectionB.Open();
datatableB = new DataTable(table);
try
{
OleDbCommand commandselectB = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionB);
adapterB.SelectCommand = commandselectB;
adapterB.Fill(datatableB);
}
catch
{
Logging.updateLog("Error: Tried to get " + table + " from DataSetB. Table doesn't exist!");
}
if (addtoDataSet == true)
{
datasetB.Tables.Add(datatableB);
Logging.updateLog("Added DataTableB: " + datatableB.TableName.ToString() + " Successfully!");
}
dataconnectionB.Close();
}
static public string[] getTablesA(string connectionString)
{
dataconnectionA.Open();
tableListA = dataconnectionA.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
string[] stringTableListA = new string[tableListA.Rows.Count];
for (int i = 0; i < tableListA.Rows.Count; i++)
{
stringTableListA[i] = tableListA.Rows[i].ItemArray[2].ToString();
}
dataconnectionA.Close();
return stringTableListA;
}
static public string[] getTablesB(string connectionString)
{
dataconnectionB.Open();
tableListB = dataconnectionB.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
string[] stringTableListB = new string[tableListB.Rows.Count];
for (int i = 0; i < tableListB.Rows.Count; i++)
{
stringTableListB[i] = tableListB.Rows[i].ItemArray[2].ToString();
}
dataconnectionB.Close();
return stringTableListB;
}
static public void createDataSet()
{
string[] tempA = getTablesA(connectionstringA);
string[] tempB = getTablesB(connectionstringB);
int percentage = 0;
int maximum = (tempA.Length + tempB.Length);
Logging.updateNotice("Loading Tables...");
for (int i = 0; i < tempA.Length ; i++)
{
if (!datasetA.Tables.Contains(tempA[i]))
{
addTableA(tempA[i], true);
percentage++;
Logging.loadStatus(percentage, maximum);
}
else
{
datasetA.Tables.Remove(tempA[i]);
addTableA(tempA[i], true);
percentage++;
Logging.loadStatus(percentage, maximum);
}
}
for (int i = 0; i < tempB.Length ; i++)
{
if (!datasetB.Tables.Contains(tempB[i]))
{
addTableB(tempB[i], true);
percentage++;
Logging.loadStatus(percentage, maximum);
}
else
{
datasetB.Tables.Remove(tempB[i]);
addTableB(tempB[i], true);
percentage++;
Logging.loadStatus(percentage, maximum);
}
}
}
static public DataTable getDataTableA()
{
datatableA = datasetA.Tables[Settings.textA];
return datatableA;
}
static public DataTable getDataTableB()
{
datatableB = datasetB.Tables[Settings.textB];
return datatableB;
}
static public DataSet getDataSetA()
{
return datasetA;
}
static public DataSet getDataSetB()
{
return datasetB;
}
static public void InitiateCopyProcessA()
{
DataSet tablesA;
tablesA = DatabaseHandling.getDataSetA();
foreach (DataTable table in tablesA.Tables)
{
CopyTable(table, connectionstringB);
}
}
public static void CopyTable(DataTable table, string connectionStringB)
{
var connectionB = new OleDbConnection(connectionStringB);
foreach (DataRow row in table.Rows)
{
InsertRow(row, table.Columns, table.TableName, connectionB);
}
}
public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection)
{
var columnNames = new List<string>();
var values = new List<string>();
for (int i = 0; i < columns.Count; i++)
{
columnNames.Add("[" + columns[i].ColumnName + "]");
values.Add("'" + row[i].ToString().Replace("'", "''") + "'");
}
string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
table,
string.Join(", ", columnNames.ToArray()),
string.Join(", ", values.ToArray())
);
ExecuteNonQuery(sql, connection);
}
public static void ExecuteNonQuery(string sql, OleDbConnection conn)
{
if (conn == null)
throw new ArgumentNullException("conn");
ConnectionState prevState = ConnectionState.Closed;
var command = new OleDbCommand(sql, conn);
try
{
prevState = conn.State;
if (prevState != ConnectionState.Open)
conn.Open();
command.ExecuteNonQuery(); // !!! Runtime-Error: Data type mismatch in criteria expression. !!!
}
finally
{
if (conn.State != ConnectionState.Closed
&& prevState != ConnectionState.Open)
conn.Close();
}
}
}
}
Why am I getting this error? Both tables are exactly the same. What am I doing wrong? Worst case, how do I delete the table in the other Access .MDB file before inserting the exact same structure table with different values in it?
Man I wish I could just figure this out...
EDIT:
Okay, I've come some distance. My question has morphed into a new one, and thus deserves being asked seperately. I have had my question answered as now I know how to execute queries directly to the connection that I have opened. Thank you all!