I have a Microsoft SQL Server database which is updated with data regularly. I would like to store this database with all tables (and preferrably relationsships) to a new Microsoft Access (.accdb) file using C#.
SQL Management Studio is installed on the system so I think one solution could be to invoke BCP (http://msdn.microsoft.com/en-us/library/ms162802.aspx) from the code, but I haven't figured out how to use it correctly in this case. I guess there are much better ways doing it without using BCP though.
Can anyone recommend a way to achieve this?
Thank you
You can import MSSQL Data in Access; More info on: http://office.microsoft.com/en-us/access-help/import-or-link-to-sql-server-data-HA010200494.aspx
Update:
Alternately you can select all tables using sqldataadapter to store everything in a dataset, see: Obtaining a dataset from a SQL Server database
From there on you can save the dataset as a access database file, see: C# Dataset to Access DB
Maybe this is more inline with your problem.
Thanks to Ferdy's suggestion I solved the problem. Since it could be of use for others I put my working code sample here:
//The connection strings needed: One for SQL and one for Access
String accessConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\...\\test.accdb;";
String sqlConnectionString = "Data Source=localhost\\SQLEXPRESS;Initial Catalog=Your_Catalog;Integrated Security=True";
//Make adapters for each table we want to export
SqlDataAdapter adapter1 = new SqlDataAdapter("select * from Table1", sqlConnectionString);
SqlDataAdapter adapter2 = new SqlDataAdapter("select * from Table2", sqlConnectionString);
//Fills the data set with data from the SQL database
DataSet dataSet = new DataSet();
adapter1.Fill(dataSet, "Table1");
adapter2.Fill(dataSet, "Table2");
//Create an empty Access file that we will fill with data from the data set
ADOX.Catalog catalog = new ADOX.Catalog();
catalog.Create(accessConnectionString);
//Create an Access connection and a command that we'll use
OleDbConnection accessConnection = new OleDbConnection(accessConnectionString);
OleDbCommand command = new OleDbCommand();
command.Connection = accessConnection;
command.CommandType = CommandType.Text;
accessConnection.Open();
//This loop creates the structure of the database
foreach (DataTable table in dataSet.Tables)
{
String columnsCommandText = "(";
foreach (DataColumn column in table.Columns)
{
String columnName = column.ColumnName;
String dataTypeName = column.DataType.Name;
String sqlDataTypeName = getSqlDataTypeName(dataTypeName);
columnsCommandText += "[" + columnName + "] " + sqlDataTypeName + ",";
}
columnsCommandText = columnsCommandText.Remove(columnsCommandText.Length - 1);
columnsCommandText += ")";
command.CommandText = "CREATE TABLE " + table.TableName + columnsCommandText;
command.ExecuteNonQuery();
}
//This loop fills the database with all information
foreach (DataTable table in dataSet.Tables)
{
foreach (DataRow row in table.Rows)
{
String commandText = "INSERT INTO " + table.TableName + " VALUES (";
foreach (var item in row.ItemArray)
{
commandText += "'"+item.ToString() + "',";
}
commandText = commandText.Remove(commandText.Length - 1);
commandText += ")";
command.CommandText = commandText;
command.ExecuteNonQuery();
}
}
accessConnection.Close();
Related
I have two almost same databases (both are *.mdb), but one of them has few new tables. Now I can only detect tables, that should be imported, using code below:
public static List<string> GetDBTables(string path)
{
List<string> allTables = new List<string>();
String connect = ("Provider=Microsoft.JET.OLEDB.4.0;data source="
+ path + ";Persist Security Info=False;");
OleDbConnection con = new OleDbConnection(connect);
con.Open();
DataTable tables = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new object[] { null, null, null, "TABLE" });
int counter = 1;
foreach (DataRow row in tables.Rows)
{
allTables.Add(row[2].ToString());
counter++;
}
con.Close();
return allTables;
}
var withNewTables = GetDBTables(".\\one.mdb");
var withoutNewTables = GetDBTables(".\\another.mdb");
var NotFoundTables = withNewTables.Except(withoutNewTables).ToList();
How can I import these tables in the old database using C #?
Access SQL offers two features which are useful here.
SELECT <field list> INTO NewTable
FROM table_name IN 'path to other db file'
So I can execute this statement from an OleDb connection to my destination db file, and it will create tblFoo_copy from the data contained in tblFoo in the other db file, NewData.mdb.
SELECT f.* INTO tblFoo_copy
FROM tblFoo AS f IN 'C:\Users\hans\Documents\NewData.mdb';
Build and execute similar statements for each of those tables you want to import.
Well, in addition to HansUp answer, I post the implementation of this on C#:
public static void insertTables(string path_from, string path_to,
List<string> _tables)
{
string conString = ("Provider=Microsoft.JET.OLEDB.4.0;data source="
+ path_to + ";Persist Security Info=False;");
OleDbConnection dbconn = new OleDbConnection(conString);
dbconn.Open();
OleDbCommand dbcommand = new OleDbCommand();
_tables.ForEach(delegate(String name)
{
string selQuery = "SELECT f.* INTO " + name + " FROM " + name
+ " AS f IN '" + path_from + "';";
dbcommand.CommandText = selQuery;
dbcommand.CommandType = CommandType.Text;
dbcommand.Connection = dbconn;
int result = dbcommand.ExecuteNonQuery();
});
dbconn.Close();
}
insertTables(".\\one.mdb", ".\\another.mdb", NotFoundTables);
My question is how can i export gridview into MS Access in C#
for this I am Using the following code:
String accessConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\...\\test.accdb;";
String sqlConnectionString = ConfigurationManager.ConnectionStrings["College"].ConnectionString;
//Make adapters for each table we want to export
SqlDataAdapter adapter1 = new SqlDataAdapter();
// SqlDataAdapter adapter2 = new SqlDataAdapter();
DataTable dtFillGrid = (DataTable)ViewState["FillGrid"];
//Fills the data set with data from the SQL database
// DataSet dataSet = new DataSet();
adapter1.Fill(dtFillGrid);
// adapter2.Fill(dataSet, "Table2");
//Create an empty Access file that we will fill with data from the data set
ADOX.Catalog catalog = new ADOX.Catalog();
catalog.Create(accessConnectionString);
//Create an Access connection and a command that we'll use
OleDbConnection accessConnection = new OleDbConnection(accessConnectionString);
OleDbCommand command = new OleDbCommand();
command.Connection = accessConnection;
command.CommandType = CommandType.Text;
accessConnection.Open();
//This loop creates the structure of the database
foreach (DataTable table in dtFillGrid.Rows)
{
String columnsCommandText = "(";
foreach (DataColumn column in table.Columns)
{
String columnName = column.ColumnName;
String dataTypeName = column.DataType.Name;
String sqlDataTypeName = getSqlDataTypeName(dataTypeName);
columnsCommandText += "[" + columnName + "] " + sqlDataTypeName + ",";
}
columnsCommandText = columnsCommandText.Remove(columnsCommandText.Length - 1);
columnsCommandText += ")";
command.CommandText = "CREATE TABLE " + table.TableName + columnsCommandText;
command.ExecuteNonQuery();
}
//This loop fills the database with all information
foreach (DataTable table in dtFillGrid.Rows)
{
foreach (DataRow row in table.Rows)
{
String commandText = "INSERT INTO " + table.TableName + " VALUES (";
foreach (var item in row.ItemArray)
{
commandText += "'" + item.ToString() + "',";
}
commandText = commandText.Remove(commandText.Length - 1);
commandText += ")";
command.CommandText = commandText;
command.ExecuteNonQuery();
}
}
accessConnection.Close();
but in this code I get an error:
The Type or Namespace name ADOX could not be found
According to accessConnectionString content you should install "Data Connectivity Components" in your machine.
It is available to download at http://www.microsoft.com/en-us/download/details.aspx?id=23734
You need to add a reference for Microsoft ADO Ext. 2.7 for DDL and Security(the version number may be different though) which can be found under the COM section of the references dialog , and then add using ADOX; in your code.
Here I did not export gridview in MS Access but I made a database in MS Access using C# with the help of this code
ADOX.Catalog cat = new ADOX.Catalog();
ADOX.Table table = new ADOX.Table();
//Create the table and it's fields.
table.Name = "Table1";
table.Columns.Append("PartNumber", ADOX.DataTypeEnum.adVarWChar, 6); // text[6]
table.Columns.Append("AnInteger", ADOX.DataTypeEnum.adInteger, 10); // Integer
try
{
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=d:/m2.accdb;" + "Jet OLEDB:Engine Type=5");
cat.Tables.Append(table);
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0;" + "Data Source=d:/m2.accdb");
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "INSERT INTO Table1([PartNumber],[AnInteger]) VALUES (#FirstName,#LastName)";
cmd.Parameters.Add("#FirstName", OleDbType.VarChar).Value = "neha";
cmd.Parameters.Add("#LastName", OleDbType.VarChar).Value = 20;
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
result = false;
}
cat = null;
I have Excel file shown bellow
I want to read 1st read only all school names & school address & insert them in SchoolInfo table of mySql database.
After that I want to read data for each school & insert it in StudentsInfo table which has foreign key associated with SchoolInfo table.
I am reading excel sheet something like this.
public static void Import(string fileName)
{
string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName +
";Extended Properties=\"Excel 12.0;HDR=No;IMEX=1\"";
var output = new DataSet();
using (var conn = new OleDbConnection(strConn))
{
conn.Open();
var dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
if (dt != null)
foreach (DataRow row in dt.Rows)
{
string sheet = row["TABLE_NAME"].ToString();
var cmd = new OleDbCommand("SELECT * FROM [+"+sheet+"+]", conn);
cmd.CommandType = CommandType.Text;
OleDbDataAdapter xlAdapter = new OleDbDataAdapter(cmd);
xlAdapter.Fill(output,"School");
}
}
}
Now I am having data in datatable of dataset, Now how do I read desired data & insert it in my sql table.
Try the following steps:
Reading from Excel sheet
First you must create an OleDB connection to the Excel file.
String connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + path + ";" +
"Extended Properties=Excel 8.0;";
OleDbConnection xlConn = new OleDbConnection(connectionString);
xlConn.Open();
Here path refers to the location of your Excel spreadsheet. E.g. "D:\abc.xls"
Then you have to query your table. For this we must define names for the table and columns first. Click here to find out how.
Now create the command object.
OleDbCommand selectCmd = new OleDbCommand("SELECT * FROM [Sheet1$]", xlConn);
Now we have to store the ouput of the select command into a DataSet using a DataAdapter
OleDbDataAdapter xlAdapter = new OleDbDataAdapter();
objAdapter1.SelectCommand = selectCmd;
DataSet xlDataset = new DataSet();
xlAdapter.Fill(xlDataset, "XLData");
Save the data into variables
Now extract cell data into variables iteratively for the whole table by using
variable = xlDataset.Tables[0].Rows[row_value][column_value].ToString() ;
Write the data from the variables into the MySQL database
Now connect to the MySQL database using an ODBC connection
String mySqlConnectionString = "driver={MySQL ODBC 5.1 Driver};" +
"server=localhost;" + "database=;" + "user=;" + "password=;";
OdbcConnection mySqlConn = new OdbcConnection(mySqlConnectionString);
mySqlConn.Open();
Construct your INSERT statement using the variables in which data has been stored from the Excel sheet.
OdbcCommand mySqlInsert = new OdbcCommand(insertCommand, mySqlConn);
mySqlInsert.ExecuteScalar()
I have two databases(SQlserver and MS Access) with same schemas (same tables). SQL server database has data but Access has no data (blank database).
My goal : when user enters a ClientId and click insert button then I need to retrive that single record from all tables in sql server database and insert into tables in MS Access Database.
Achieved: i retrived from all tables in sql server databases with client id and stored the data in Dataset.
i have table array and i am looping thru all tables in array and trying to insert data from above dataset into Ms Access dynamically.
Can you suggest how insert into Access for all tables dynamically in loop . i cannot wrie insert statement for each table. i need one which is generic for every table so that i will pass parametrs. Its not a bulk insert, its single record push into multiple tables.
-------This is My code-------------------------------------------------------
private void InsertMsiClientIntoTest(string ClientId)
{
SqlConnection sqlConnection = null;
SqlDataAdapter sqlDataAdapter = null;
DataSet sqlserverDataset = new DataSet();
sqlserverDataset.Tables.Add();
sqlConnection = new SqlConnection();
sqlConnection = new SqlConnection("Data Source=THINK;Initial Catalog=" + dbName + ";Integrated Security=True;");
sqlConnection.Open();
sqlDataAdapter = new SqlDataAdapter(ClientSQL.PopulateTables, sqlConnection);
sqlDataAdapter.SelectCommand.Parameters.AddWithValue("#ClientId", cmbId.Text);
sqlDataAdapter.Fill(sqlserverDataset);
GetDataFromTablesForID(sqlserverDataset);
InsertAllTableDataIntoAccess(sqlserverDataset,tableArray);
}
private DataSet GetDataFromTablesForID(DataSet dsTablesList)
{
SqlConnection sqlConnection = null;
SqlDataAdapter sqlDataAdapter = null;
string tableName = string.Empty;
string QueryText = string.Empty;
int i =0;
tableArray = new string[dsTablesList.Tables[0].Rows.Count];
DataSet sqlserverDataset = new DataSet();
sqlserverDataset.Tables.Add();
sqlConnection = new SqlConnection();
sqlConnection = new SqlConnection("Data Source=THINK;Initial Catalog=" + dbName + ";Integrated Security=True;");
sqlConnection.Open();
foreach (DataRow itemRow in dsTablesList.Tables[0].Rows)
{
tableArray[i] = itemRow[0].ToString();
i++;
}
foreach (string tableItem in tableArray)
{
tableName = tableItem;
QueryText = "select x.* from" + " " + tableName + " " +
"x inner join ClientMajor ci on ci.ClientId = x.ClientId where ci.MajorClientId =#ClientId";
}
sqlDataAdapter = new SqlDataAdapter(QueryText, sqlConnection);
sqlDataAdapter.SelectCommand.Parameters.AddWithValue("#ClientId", cmbExceedId.Text);
sqlDataAdapter.Fill(sqlserverDataset);
}
return sqlserverDataset;
}
private void InsertAllTableDataIntoAccess(DataSet Inputset, string[] tableArray)
{
string connectionstring = System.Configuration.ConfigurationManager.ConnectionStrings["mdb"].ToString();
OleDbConnection oledbConnection = null;
OleDbDataAdapter oledbDataAdapter = null;
DataSet resultSet = new DataSet();
oledbConnection = new OleDbConnection(connectionstring);
oledbConnection.Open();
foreach (string tableItem in tableArray)
{
//????????? I NEED THE FOLLOWING CODE......////////////???????
oledbDataAdapter.InsertCommand.CommandText="insert into "
oledbDataAdapter.Fill(resultSet.Tables[0]);
}
}
Thanks in Advance...
the best way to do that is to :
first, insert data on sql server
secondly,use a ssis package to export data from sql server to access database
SSIS is usefull in you case ( create a data folw with sql server as datasource, your query, and ms access as data destination )
I have a dataset that is dynamically created from a csv file. What I want to do is insert the rows into my MS Access table but I cannot figure out where to start with this.
The headers of the data in the dataset can vary as far as the order but the name of the header will always match the access database. Do I have to statically call out the header name in the insert command or can I build the headers from the dataset?
I know how to create the connection and open it to the database but am not sure how to create in insert command to dynamically pull the table headers.
I am pretty green when it comes to C# programming so if you can spell it out for me I would really appreciate it!
Here is an example of the access table headers:
ID, Item, Cost, Retail
Then the CSV which will fill the dataset table. It might have Retail or it might not:
Item, Cost
Here is the code I have so far but it doesn't write to the access table. If I vew the dtAccess it shows correctly.
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\"C:\\Database.accdb\";Persist Security Info=False;");
myConnection.Open();
string queryString = "SELECT * from " + lblTable.Text;
OleDbDataAdapter adapter = new OleDbDataAdapter(queryString, myConnection);
DataTable dtAccess = new DataTable();
DataTable dtCSV = new DataTable();
dtCSV = ds.Tables[0];
using (new OleDbCommandBuilder(adapter))
{
adapter.Fill(dtAccess);
dtAccess.Merge(dtCSV);
adapter.Update(dtAccess);
}
myConnection.Close();
Figured it out. Here is the code I used:
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\"Database.accdb\";Persist Security Info=False;");
//command to insert each ASIN
OleDbCommand cmd = new OleDbCommand();
//command to update each column (ASIN, Retail... from CSV)
OleDbCommand cmd1 = new OleDbCommand();
//load csv data to dtCSV datatabe
DataTable dtCSV = new DataTable();
dtCSV = ds.Tables[0];
// Now we will collect data from data table and insert it into database one by one
// Initially there will be no data in database so we will insert data in first two columns
// and after that we will update data in same row for remaining columns
// The logic is simple. 'i' represents rows while 'j' represents columns
cmd.Connection = myConnection;
cmd.CommandType = CommandType.Text;
cmd1.Connection = myConnection;
cmd1.CommandType = CommandType.Text;
myConnection.Open();
for (int i = 0; i <= dtCSV.Rows.Count - 1; i++)
{
cmd.CommandText = "INSERT INTO " + lblTable.Text + "(ID, " + dtCSV.Columns[0].ColumnName.Trim() + ") VALUES (" + (i + 1) + ",'" + dtCSV.Rows[i].ItemArray.GetValue(0) + "')";
cmd.ExecuteNonQuery();
for (int j = 1; j <= dtCSV.Columns.Count - 1; j++)
{
cmd1.CommandText = "UPDATE " + lblTable.Text + " SET [" + dtCSV.Columns[j].ColumnName.Trim() + "] = '" + dtCSV.Rows[i].ItemArray.GetValue(j) + "' WHERE ID = " + (i + 1);
cmd1.ExecuteNonQuery();
}
}
myConnection.Close();
Access has hidden tables that provide database access to the tables and columns in the database. The names of them are dependent upon access version, but they're typically something like systables? It's been a while, but if you "show hidden tables" you should be able to find them.
If the the two datatable have the same structure you can merge the "CSV" Datatable with the Database table datatable, so for example you can retrieve the database table into a datatable using a data adapter :
string queryString = "SELECT * FROM sometable";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);
DataTable dtAccess = new DataTable();
adapter.Fill(dtAccess);
then you can merge the content of this DataTable with the content of the CSV DataTable :
dtAccess.Merge(dtCSV);
After that you can write the content of the datatable into the access database table with a command builder :
using (new SqlCommandBuilder(adapter)) {
adapter.Update(dtAccess);
}
If the datatables have the same structure should work without any problem ...