SQL Server CE与远程Access数据库双向同步

时间:2017-04-07 13:09:57

标签: c# xml ms-access sql-server-ce windows-mobile-6.5

我正在开发一个非常特殊的遗留项目,我需要在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);
            }

        }
    }

1 个答案:

答案 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同步工具。