我正在开发一个非常特殊的遗留项目,我需要在Windows Mobile 6.5下为PDA设备构建应用程序。这些设备有一个本地数据库(SQL Server CE),只要它们停靠并具有网络访问权限,我们就可以与远程数据库同步(Microsoft Access)。
因此使用SQL Server CE的本地数据库工作正常,但我无法找到将其正确同步到Access数据库的方法。
我读到在Windows Mobile 6.5下不支持ODBC和OLEDB,我发现大多数资源都已过时或有空链接,我发现的唯一方法是以XML格式导出本地数据库相关表希望为Access构建一个VBA组件以正确导入它们。 (并找出向后同步)。
首先,感谢所有提供有用答案的人,感谢@josef在this thread上使用自动路径为我节省了大量时间。
因此,出于安全原因,远程SQL Server是不可取的(客户端对安全性感到偏执,并且不能为我提供服务器)。因此,我在PDA和计算机上的Access上绑定了SQL Server CE。
至于同步:
导出很好:我在使用多个dataAdapter和WriteXML方法生成设备重新插入时由FTP传输的XML文件。然后,这些文件会自动导入Access数据库。 (见最后的代码)。
我的问题在于输入:我可以通过XML读取器从Access生成的文件中获取数据。然后将这些数据插入到数据集中(实际上,我甚至可以在PDA屏幕上打印数据),但是我无法找到一种方法来进行数据管理。#UPS;"在PDA的数据库。因此,如果数据已经包含具有相同ID的数据,我需要一种创新的方式来更新/插入表格。
我尝试了两种方法,SQL错误(根据我的理解,SQL Server CE不处理存储过程或T-SQL)。一个简单的查询示例,该查询应该更新" available"一些存储点的标志:
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);
}
我也尝试了这个查询,同样的问题SQL服务器显然没有处理ON DUPLICATE KEY(我认为它是MySQL特定的)。
INSERT INTO spots (spot, available)
VALUES(@spot, @available)
ON DUPLICATE KEY UPDATE spots SET available=@available
导出方法的代码已修复,因此工作正常但仍然适合任何想要了解的人:
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);
}
}
}
答案 0 :(得分:2)
由于Access或多或少是一个独立的数据库解决方案,我强烈建议使用完整的SQL Server和IIS来设置SQL CE数据和SQL Server数据之间的合并复制同步。
Paul Yao和David Durant撰写的“编程.Net Compact Framework”一书(第8章,同步移动数据)中的完整示例代码和设置对此进行了描述。
对于工作同步,必须跟踪服务器和CE设备上定义的表和数据的所有更改(通过GUID,唯一编号完成),并且时间戳和冲突处理必须定义。
如果数据永远不会通过服务器上的其他方式更改,您可以只跟踪设备端更改,然后将它们推送到Access数据库。这可以通过另一个执行Buld更新的应用来完成,如here所述。
如果您不想以昂贵的方式使用SQL Server,那么可以使用免费的SQLite(可用于CE和Compact Framework)以及用于SQLite到MSAccess的商业同步工具(如DBSync)。 / p>
如果您有经验,可以创建自己的SQLite到MS ACCESS同步工具。