0

下面讲述了“故事的其余部分”的所有血腥细节,但切入正题,归结为:

SQLCE 2.0(包含在 sqlce.wce4.armv4.CAB 中)似乎安装在我的应用程序运行的设备上;源项目引用运行时版本为 v2.0.50727 和版本为 3.5.1.0 的 SqlServerCe

这是匹配还是不匹配?如果是后者,我需要在我的项目中引用哪个版本的 SqlServerCe.dll?

血腥故事的其余部分

我的 Windows CE 应用程序在尝试打开 SQL CE (.SDF) 文件时失败;尽管一个潜在的早期问题显然与版本控制有关(没有双关语)(调用 SqlCeEngine.Upgrade() 让我过去了),错误消息现在表明密码问题。看到这个

但是我看不到在表上设置密码的位置 - 也看不到指定 SQLCE 版本的位置。

我们有一个安装实用程序,可以在手持设备上安装此应用程序以及必要的辅助文件。为了弄清楚这两个应用程序(正确的安装应用程序)在版本控制和密码方面到底做了什么,我在两个代码库中搜索了“SDF”和“SQLCE”,这是我发现的*:

设置实用程序中对“SDF”的唯一引用是:

{_T("OpenNETCF.SDF.WCE4.ARMV4.CAB"),_T("OpenNETCF SDF v1.4"),(DWORD)0,true},

应用程序本身中对“SDF”的唯一引用不会创建SqlCe(“SDF”)数据库。如果确实存在此类引用,它们会查找已存在的特定 SDF 文件,如下所示:

filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "HHSDB.SDF");

然后引擎数据库引擎被实例化和升级,并有条件地创建一个数据库(在我的例子中,文件存在,所以不调用 CreateDatabase()):

engine = new SqlCeEngine(conStr);
engine.Upgrade(conStr); // <= Recommended by ctacke

if (File.Exists(filename))
{
    MessageBox.Show(string.Format("file {0} exists", filename)); // TODO: Comment out or remove
}
else
{
    engine.CreateDatabase(); 
}

安装实用程序中对“SQLCE”的唯一引用是:

0)

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by HHSetupCon.rc
//
. . .
#define IDR_NETCF                       103
#define IDR_SQLCLIENT                   104
#define IDR_SQLCEDEV                    105
#define IDR_SQLCE                       106
. . .

1)

IDR_SQLCLIENT           BIN                     "J:\\sql.wce4.armv4.zip"
IDR_SQLCEDEV            BIN                     "J:\\sqlce.dev.wce4.armv4.zip"
IDR_SQLCE               BIN                     "J:\\sqlce.wce4.armv4.zip"

2)

{_T("sqlce.dev.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0 Dev"),IDR_SQLCEDEV,false},
{_T("sqlce.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0"),IDR_SQLCE,false},

应用程序本身对“SQLCE”的引用会创建或查询 SDF 表,例如:

// This creates a table (a *table*, not the database itself)
public static void CreateSettingsTable()
{
    try
    {
        string sqlddl =
            "create table platypus_settings (setting_id int identity (1,1) Primary key,  setting_name nvarchar(40) not null, setting_value nvarchar(63))";
        DBConnection.GetInstance().DBCommand(sqlddl, false);
    }
    catch (SqlCeException sqlcex)
    {
        SSCS.ExceptionHandler(sqlcex, "DBUtils.CreateSettingsTable");
    }
    catch (Exception ex)
    {
        SSCS.ExceptionHandler(ex, "DBUtils.CreateSettingsTable");
    }
}

注意:DBConnection 是一个自定义类,其中包含一些 SqlCe* 成员:

SqlCeConnection objCon = null;
SqlCeEngine engine;
public SqlCeTransaction SqlTrans;

...因此,实用程序和应用程序本身似乎都没有创建SqlCe数据库(HHSDB.SDF) - 应用程序只需找到 .SDF 文件,然后从中读取/写入。

似乎当应用程序创建一个表(如上面的 CreateSettingsTable() )和类似活动时,它会使用 SqlCe DLL 来执行此操作,并且由于 ctacke 说该 DLL 的版本(设备上的那个)有与项目源代码相关的那个,实际上应该在设备上有一个,但是由于我在设备上没有看到任何SqlCe DLL,因此无法验证设备上的版本和项目构建环境是否匹配。 ..

具体来说:设备上没有sqlserverce.dll;是我应该寻找的其他文件吗?缺少此 DLL 本身一定不是问题,否则我将无法通过以下代码(我会这样做):

engine = new SqlCeEngine(conStr);

项目中引用的 System.Data.SqlServerCe DLL 为 Runtime Version "v2.0.50727", Version "3.5.1.0"

安装项目没有这样的引用,AFAICT(它是一个 C++ 项目)。但是,它确实有以下代码:

{_T("sqlce.dev.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0 Dev"),IDR_SQLCEDEV,false},
{_T("sqlce.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0"),IDR_SQLCE,false},

所以它为 SQL CE 版本 2 安装 cab 文件...这里的版本 2 是否与应用程序引用的 SqlServerCE DLL 中的“运行时版本”或“版本”相对应?

我认为这些 cab 应该被扩展/包含 SqlCe DLL [s] 但是,正如我所写的,在运行这个 setup util 之后我在设备上看不到任何东西(这似乎工作正常)。

所以,总结和重申:

SQLCE 2.0(包含在 sqlce.wce4.armv4.CAB 中)似乎安装在我的应用程序运行的设备上;源项目引用运行时版本为 v2.0.50727 和版本为 3.5.1.0 的 SqlServerCe

这是匹配还是不匹配?如果是后者,我需要在我的项目中引用哪个版本的 SqlServerCe.dll?

  • “入境口岸的警察说……” - 对不起,我忍不住(或者不想更喜欢它)

更新

这些是设备上的一些文件:

在此处输入图像描述

更新 2

尽管如此,表面上很明显,根据文件名,这些是 3.5 版,我在 JetBrains 的 dotPeek 中打开它们以试图验证这一点,但结果平淡无奇 - 我得到这些 DLL 的“(不支持)”。

在 Reflector 中尝试同样的事情给了我更多信息:“'C:\Bla\sqlceca35.dll' 不是 .NET 模块。”

4

1 回答 1

1

是的,你有一个不匹配。

您有一个内部指示它是 SQL Compact 2.0 文件的数据库文件。

您有一个版本为 3.5.1 的 System.Data.SqlServerCe.dll 程序集。“运行时版本”是指它是针对什么 CF 运行时构建的,所以它是针对 2.0 运行时构建的——这并不意味着它本身就是 2.0。这是混淆点——你一直命名两个版本,而一个程序集只有一个版本。

这是我的怀疑,因为您正在调用SQL Compact 2.0Upgrade()甚至不存在的调用。

如果您想以原始状态打开原始数据库,并允许原始创建者仍然可以访问它(并且必须有创建它的代码或者它已经部署在 CAB 文件中,没有隐含的方法它可能会发生)然后我再次重申,您必须使用相同版本的 SQL Compact 来执行此操作。

在您的具体情况下,这意味着您应该执行以下操作:

  1. 将项目引用(这意味着在您的 PC 上的 Studio 中)更改为指向具有 2.0.xxx 程序集版本的 System.Data.SqlServerCe.dll。
  2. 确保设备上具有完全相同的版本 (2.0.xxx) 编号的 SQL Compact 文件。这包括 System.Data.SqlServerCe.dll 以及所有 sscexx.dll 本机文件。大约有半打。

除非您想将其设为 3.5 数据库,否则您无需调用Upgrade(),此时您无法返回,而且您每次运行时都会尝试升级,我怀疑这是否是您想要的。该方法通常用于公用事业或一次性使用。

您的 PC 上有多少其他版本的程序集并不重要,事实上您也可以在设备上拥有多个版本。重要的是,您在项目引用中拥有的内容(即应用程序链接到的内容)与应用程序实际执行时在设备上加载的 DLL 相同。

通常我会做两件事来确保发生这种情况:

  1. 将所有 SQL CE 内容直接放入设备上的 app 文件夹中,而不是通过 CAB 分发,而是部署每个单独的文件,以确保发生这种情况。
  2. 直接参考您 PC 上的文件。不要使用 Studio 查找 .NET 引用的“魔术”方法,而是直接浏览到您认为正确的 System.Data.SqlServerCe.dll并以这种方式添加引用。
于 2014-05-06T22:26:39.470 回答