I'm trying to figure out how to connect a website form to an external Microsoft Access database. The website and database are on different servers. The website is going through a hosting company and the database is located inside a company office network.
My goal is to have users fill out an online form and then that information will be sent and saved to the Access database.
Is there a tutorial on this or does anyone have any suggestions?
TODO: You'll need to change the path to the mdb (in the connection string), probably hook up to some button click event instead of form load, change the table name (tblYourData) and the field names (field1, field2, etc) in the sql string, and instead of using 'some text', use the .Text property of the textbox on the page.
protected void Form_Load()
{
string connstring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\mydatabase.mdb;User Id=admin;Password=;";
string sql = "insert into tblYourData (field1, field2) values ('some text', 'some more text')";
CreateCommand(sql, connstring);
}
private static void CreateCommand(string queryString, string connectionString)
{
using (OleDbConnection connection = new OleDbConnection(
connectionString))
{
OleDbCommand command = new OleDbCommand(queryString, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
--Edit #1 --
This can only be done with the MDB is located on the same network (local hard drive, or network file share) as the IIS server.
Considering this isn't possible, you have a couple of options.
Option 1:
Save it to a local database (sql express, sql server, etc...)
Allow them to set up a linked server between the access database and your database.
Option 2:
Save it to a local database (sql express, sql server, etc...)
Allow them to export the data to a CSV or similar format.
Then they can import that data into their Access database.
Related
I'm working on a pretty special, legacy project where I need to build an app for PDA devices under Windows Mobile 6.5. The devices have a local database (SQL Server CE) which we are supposed to sync with a remote database (Microsoft Access) whenever they are docked and have network access.
So the local database using SQL Server CE works fine, but I can’t figure out a way to sync it to the Access database properly.
I read that ODBC and OLEDB are unsupported under Windows Mobile 6.5, most ressources I find are obsolete or have empty links, and the only way I found was to export the local database relevant tables in XML in the hope to build a VBA component for Access to import them properly. (and figure out backwards sync).
Update on the project and new questions
First of all, thanks to everyone who provided an useful answer, and to #josef who saved me a lot of time with the auto path on this thread.
So a remote SQL Server is a no go for security reasons (client is paranoid about security and won't provide me a server). So I'm tied to SQL Server CE on the PDA and Access on the computer.
As for the sync:
The exportation is fine: I'm using multiple dataAdapters and a WriteXML method to generate XML files transmitted by FTP when the device is plugged back in. Those files are then automatically imported into the Access database. (see code at the end).
My problem is on the importation: I can acquire data through XML readers from an Access-generated file. This data is then inserted in a dataset (In fact, I can even print the data on the PDA screen) but I can't figure out a way to do an "UPSERT" on the PDA's database. So I need a creative way to update/insert the data to the tables if they already contains data with the same id.
I tried two methods, with SQL errors (from what I understood it's SQL Server CE doesn't handle stored procedures or T-SQL). Example with a simple query that is supposed to update the "available" flag of some storage spots:
try
{
SqlCeDataAdapter dataAdapter = new SqlCeDataAdapter();
DataSet xmlDataSet = new DataSet();
xmlDataSet.ReadXml(localPath +#"\import.xml");
dataGrid1.DataSource = xmlDataSet.Tables[1];
_conn.Open();
int i = 0;
for (i = 0; i <= xmlDataSet.Tables[1].Rows.Count - 1; i++)
{
spot = xmlDataSet.Tables[1].Rows[i].ItemArray[0].ToString();
is_available = Convert.ToBoolean(xmlDataSet.Tables[1].Rows[i].ItemArray[1]);
SqlCeCommand importSpotCmd = new SqlCeCommand(#"
IF EXISTS (SELECT spot FROM spots WHERE spot=#spot)
BEGIN
UPDATE spots SET available=#available
END
ELSE
BEGIN
INSERT INTO spots(spot, available)
VALUES(#spot, #available)
END", _conn);
importSpotCmd.Parameters.Add("#spot", spot);
importSpotCmd.Parameters.Add("#available", is_available);
dataAdapter.InsertCommand = importSpotCmd;
dataAdapter.InsertCommand.ExecuteNonQuery();
}
_conn.Close();
}
catch (SqlCeException sql_ex)
{
MessageBox.Show("SQL database error: " + sql_ex.Message);
}
I also tried this query, same problem SQL server ce apparently don't handle ON DUPLICATE KEY (I think it's MySQL specific).
INSERT INTO spots (spot, available)
VALUES(#spot, #available)
ON DUPLICATE KEY UPDATE spots SET available=#available
The code of the export method, fixed so it works fine but still relevant for anybody who wants to know:
private void exportBtn_Click(object sender, EventArgs e)
{
const string sqlQuery = "SELECT * FROM storage";
const string sqlQuery2 = "SELECT * FROM spots";
string autoPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); //get the current execution directory
using (SqlCeConnection _conn = new SqlCeConnection(_connString))
{
try
{
SqlCeDataAdapter dataAdapter1 = new SqlCeDataAdapter(sqlQuery, _conn);
SqlCeDataAdapter dataAdapter2 = new SqlCeDataAdapter(sqlQuery2, _conn);
_conn.Open();
DataSet ds = new DataSet("SQLExport");
dataAdapter1.Fill(ds, "stock");
dataAdapter2.Fill(ds, "spots");
ds.WriteXml(autoPath + #"\export.xml");
}
catch (SqlCeException sql_ex)
{
MessageBox.Show("SQL database error: " + sql_ex.Message);
}
}
}
As Access is more or less a stand-alone DB solution I strongly recommend to go with a full flavored SQL Server plus IIS to setup a Merge Replication synchronisation between the SQL CE data and the SQL Server data.
This is described with full sample code and setup in the book "Programming the .Net Compact Framework" by Paul Yao and David Durant (chapter 8, Synchronizing Mobile Data).
For a working sync, all changes to defined tables and data on the server and the CE device must be tracked (done via GUIDs, unique numbers) with there timestamps and a conflict handling has to be defined.
If the data is never changed by other means on the server, you may simply track Device side changes only and then push them to the Access database. This could be done by another app that does Buld Updates like described here.
If you do not want to go the expensive way to SQL Server, there are cheaper solutions with free SQLite (available for CE and Compact Framework too) and a commercial Sync tool for SQLite to MSAccess like DBSync.
If you are experienced, you may create your own SQLite to MS ACCESS sync tool.
I am executing SQL command INSERT like this in my Visual C#.NET using MS VS 2010 Express Edition:
private void btnAdd_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(Properties.Settings.Default.loginDBConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO tblEmp (ID, firstname, lastname, email, position) VALUES ('"+textBox1.Text+"','"+textBox2.Text+"', '"+textBox3.Text+"', '"+textBox4.Text+"', '"+comboBox1.Text+"')", con);
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Data Added!");
}
When executing this, the MessageBox showed up which means the execution was successful. But, when I checked on the table , the data that I am trying to insert before isn't appear at all.
I have one database (loginDB.mdf) with 2 tables inside :
- TblLogin - contains username and password for login purpose which executed successfully.
- tblEmp - contains employee data, this is the one that I tried to insert data to.
What I don't understand is why the MessageBox appear when in fact none inserted into my tblEmp.
EDIT : ConnectionString to loginDB.mdf :
Data Source=.\SQLEXPRESS;AttachDbFilename="C:\Users\Andreas\documents\visual studio 2010\Projects\LoginApplication\LoginApplication\loginDB.mdf";Integrated Security=True;User Instance=True
The database name is loginDB.mdf instead of logindatabase.mdf as previously written. I changed it to loginDB.mdf just to test it, but still no changes appear.
If your c# code executes without any exceptions, it updates the database too. You have probably used AttachDbFilename=|DataDirectory|\yourDB.mdf in your ConnectionString, that means the databse that is updated is located in the subfolder BIN\DEBUG folder of your project. If you want to see the updated data just attach the database located in the bin/debug folder in ssms.
for more details read this post.
Also make sure your table in server explorer is not already open, if it is already open you must refresh it to show updated data. Please note:as mentioned in the comments you should always use parameterized queries to avoid Sql Injection.
I'm developing a C# application and I want to copy a whole table from a SQL Server CE database to another programmatically. I know I can use this command in SQL Server, but I'm not sure how to use two database connections in one query in C#.
Select * into DestinationDB.dbo.tableName from SourceDB.dbo.SourceTable
Thanks in advance.
You wouldn't do it the same way as in SQL Server because there's no single server that manages both databases. Your app is the only thing that links the two databases so the the data has to go through your app. You're trying to do it the wrong way and that's why you can't find a solution: you're looking for the wrong thing.
There are examples of this out there. I know, because I've written more than one myself. You simply need to use a data adapter to populate a DataTable from the first database and then a data adapter to save the contents of that DataTable to the second database. If the data sources are the same type then you can even use just one data adapter because the SelectCommand and InsertCommand can have different connections.
using (var adapter = new SqlDataAdapter("SELECT statement here", "source connection string here"))
using (var destinationConnection = new SqlConnection("destination connection string here"))
using (var insertCommand = new SqlCommand("INSERT statement here", destinationConnection))
{
// Add parameters to insertCommand here.
adapter.InsertCommand = insertCommand;
// Leave the RowState of all DataRows as Added so they are ready to be inserted.
adapter.AcceptChangesDuringFill = false;
var table = new DataTable();
// Retrieve data from source and save to destination.
adapter.Fill(table);
adapter.Update(table);
}
That example uses SqlClient but it works the same for any provider, including SqlServerCe.
I would like to get all the details of a single table from Remote server DB to my local DB, during page load event which should happen as a back end process can any one help me over this issue.
NOTE:
Server DB table Columns may slightly differ from local DB.
Each time when a new user is added in the server, it should update the local DB when the UserPage.aspx page is loaded.
Tools using: ASP.NET,SQL SERVER 2008.
Eg: Let the DB name be sample and the table name is customer
**Table Header in Server DB:** Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob
**Table Headers in Local DB:** Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob,Cus_password
Once the page gets loaded all the data in Customer table from serve DB should be synchronized to localDB
Asuming that the database login has access to both db's you can execute the following string as one command through your database connections.
--empty local table
truncate table [sample]..customer;
--fill local table
insert into [sample]..customer
(Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob)
select Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob from serverDb..Customer;
This will get you startet, but this is not good architecture. You might want to put a trigger on the table in the server database that will insert the new row in your local database everytime there is a new row in the serverDb.
edit
showing the whole process
protected void Page_Load(object sender, EventArgs e){
string sql = #"--empty local table
truncate table [sample]..customer;
--fill local table
insert into [sample]..customer
(Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob)
select Cus_id,Cus_name,Cus_address,Cus_email,Cus_mob from serverDb..Customer;";
var conn = new SqlConnection("Server=localhost;Database=sample;User Id=myUserName;Password = myPassword");
var cmd = conn.CreateCommand();
cmd.CommandText = sql;
conn.Open();
cmd.ExecuteNonQuery();
}
I will advice you SCHEDULE a job to load record to localdb from the backend every 15mins interval. You can use management studios to achieve that.
How do I insert data into a .dbf format database using SQL in Visual c#?
Is it same as when using MS Access?
OleDbConnection dbConn = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\wz\Desktop\UBS\onetimecapture\onetimecapture\onetimecapture\bin\Debug\;Extended Properties=dBase IV;");
try
{
// Open connection.
dbConn.Open();
//string queryCutting = "INSERT INTO cuttingstatus.dbf ([Status]) VALUES(adddate)";
string queryCutting = "INSERT INTO cuttingstatus.dbf VALUES(adddate)";
OleDbCommand command_cutting = new OleDbCommand(queryCutting, dbConn);
command_cutting.Parameters.AddWithValue("adddate", "123");
command_cutting.ExecuteNonQuery();
dbConn.Close();
}
catch
{
MessageBox.Show("Error", "SCADA system", MessageBoxButtons.OK);
}
but it return an error say that
The Microsoft Jet database engine could not find the object
'cuttings'.
Make sure the object exists and that you spell its name and the path name correctly.
The database is called cuttingstatus.dbf, and it consist of only a single column Status.
Thanks for the help =)
What is the name of the table in the cuttingstatus.dbf?
The statement should be something like:
INSERT INTO TABLE_NAME
VALUES(adddate)
as the value of the variable queryCutting.
When making an OleDbConnection to use Database files, you want your connection source to point to the logical PATH WHERE the table is... not the actual table.
Connection dbConn = new OleDbConnection(#"Data ource=C:\SomePath\WhereAreAllTables;Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBase IV;");
Then, your insert query does not reference the .dbf extension... it is implied by the connection. Also, even though it may be a single column, it would be better to explicitly show the column and values such as :
string queryCutting = "INSERT INTO cuttingstatus ( YourColumnName ) VALUES ( #adddate )";
Next... Is it really a DBase IV system? FoxPro table? Clipper? I would ensure proper provider. If the data is actually from Foxpro origin, I would go to Microsoft and download the Visual Foxpro OleDb provider.
One final thought... is that the error is referring to a truncated table name of up to 8 characters "cuttings" which implies old DOS 8.3 file naming convensions. Don't know if that is what you are also running into for your problem.