0

我的 Windows CE 应用程序中有一个 SQL Server CE 数据库。我可以在服务器资源管理器的项目中看到它(HHS.sdf):

在此处输入图像描述

...但是表格的 Columns 文件夹不会扩展;点击它们给了我:

在此处输入图像描述

HHS.sdf 的路径属性为:

Data Source=Mobile Device\Program Files\hhs\HHS.sdf

如果路径无效,为什么服务器资源管理器会向我显示数据库?如果我在服务器资源管理器中创建一个新连接(通过从数据连接上下文菜单中选择“添加连接...”),我可以导航到设备上的 .SDF 文件(\Program Files\hhs),在“添加连接”对话框:

在此处输入图像描述

...并获得“测试连接成功”的证实。

但是在运行时,当尝试填充其中一个表时:

var dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(Int32)));
dt.Columns.Add(new DataColumn("DeptNumber", typeof(Int32)));
dt.Columns.Add(new DataColumn("DeptName", typeof(string)));

foreach (HHSUtils.Department dept in depts)
{
    try
    {
        dt.Rows.Add(dept.Id, dept.DeptNumber, dept.DeptName);
        countAdded++;
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("deptId == {0}, deptNumber == {1},  
          deptName == {2} ({3})", dept.Id, dept.DeptNumber, dept.DeptName, ex.Message));
    }
}
// Now move it all into the table
using (var bc = new SqlCeBulkCopy(dataSource))
{
    bc.DestinationTableName = "Departments";
    bc.WriteToServer(dt);
}

...我在 WriteToServer() 行上得到“源列 'DEPTNUM' 不存在且目标不允许空值”。

在调试器中评估“dt”,我看到 DataSet 属性有一个红色的“错误”图标,并显示“无法评估表达式”;“Site”和“XMLTest”属性也是如此;dataSet(相对于 DataSet)属性为空。

“DEPTNUM”这个词没有出现在客户端源代码中,也没有出现在服务器源代码中......

InventoryItems 表的相同代码在没有错误消息的情况下执行(但列在服务器资源管理器中仍然非常害羞)。

我正在以这种方式创建表格:

// Got this from http://stackoverflow.com/questions/20254214/how-can-i-programmatically-determine-if-a-table-exists-within-a-sql-server-ce-da/20339969?noredirect=1#20339969
public static bool TableExists(SqlCeConnection connection, string tableName)
{
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        var sql = string.Format(
            "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", tableName);
        command.CommandText = sql;
        var count = Convert.ToInt32(command.ExecuteScalar());
        return (count > 0);
    }
}

public static void ConditionallyCreateTables()
{
    const string sdfPath = @"\Program Files\hhs\HHS.sdf";
    string dataSource = string.Format("Data Source={0}", sdfPath);

    if (!File.Exists(sdfPath))
    {
        using (var engine = new SqlCeEngine(dataSource))
        {
            engine.CreateDatabase();
        }
    }

    using (var connection = new SqlCeConnection(dataSource))
    {
        connection.Open();
        using (var command = new SqlCeCommand())
        {
            command.Connection = connection;

            // It may be that I'll want to replace "if (!TableExists())" with "if (TableExists())" and then either drop the table in that
            // case and recreate it, or delete its contents
            if (!TableExists(connection, "InventoryItems"))
            {
                command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Departments"))
            {
                command.CommandText = "CREATE TABLE Departments (Id int NOT NULL, DeptNum int NOT NULL, DepartmentName nvarchar(255))";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Subdepartments"))
            {
                command.CommandText = "CREATE TABLE Subdepartments (Id int NOT NULL, DeptId int NOT NULL, SubdeptId int NOT NULL, DepartmentName nvarchar(255))";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Redemptions"))
            {
                command.CommandText = "CREATE TABLE Redemptions (Id int NOT NULL, RedemptionId nvarchar(50), RedemptionItemId nvarchar(50), RedemptionName nvarchar(255), RedemptionAmount numeric, RedemptionDept nvarchar(50), RedemptionSubdept nvarchar(50))";
                command.ExecuteNonQuery();
            }
        }
    }
}

[{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }] [{ }]

顺便说一句,我得出的结论是(经过 20 年在这个职业盐矿的墙壁上凿开,并成为无数严重程度不同的塌方 [*] 的不幸受害者)计算机程序员要么需要精神错乱(这样您就不会被这一切的乏味所驱使)或绝对不受精神错乱(出于同样的原因);如果您从频谱的任一端开始,您可能会没事的;但是,对于那些处于这种连续性中间的人(我认为他们是普通民众的很大一部分):小心,以免您的感官被压成无形的纸浆或堆积成尖叫(如果被闷住)疯狂。

[*****] 是的,真的,每次挖掘时,我都发现我的手在流血的手里抓着镐。

更新

我通过确保临时表中的列名与 SQL Server CE 表中的列名完全对应来解决“DEPTNUM”错误(根据服务器资源管理器,无论如何都不存在):

var dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(Int32)));
dt.Columns.Add(new DataColumn("DeptNum", typeof(Int32)));
dt.Columns.Add(new DataColumn("DepartmentName", typeof(string)));

然而,正如上面所暗示的,主要难题(帖子的名义问题)仍未解决。

更新 2

让电脑打个盹并“想一想”并没有任何帮助。今天也是如此。将记录添加到 SQL Server CE 表的代码工作正常;只是服务器资源管理器,虽然能够正常连接到手持设备的数据库文件(测试连接成功)看不到文件,还是假装看不到?BTW / AWTTW:我将尽快(明天某个时候)奖励这个。

更新 3

本次测试:

if (!File.Exists(sdfPath))
{
    using (var engine = new SqlCeEngine(dataSource))
    {
        engine.CreateDatabase();
    }
}

...失败(未输入条件代码),因此手持/Windows CE 应用程序确实将文件视为在运行时存在。

更新 4

我能够读取和写入表格,所以应用程序肯定可以看到它们;我还可以通过导航到 .SDF 文件来查看手持设备上的表格及其数据;双击 .SDF 文件时调用 SQL Server CE 工具。不过,Visual Studio 2008 中的服务器资源管理器需要唤醒。

4

1 回答 1

1

首先我要说的是,我从来没有使用过“添加连接”的东西来尝试直接连接到设备上的数据库。过去十几年的 Windows CE 开发经验告诉我,几乎任何需要 PC 与调试器本身之外的设备之间交互的东西都充满了危险。ActiveSync == 地图上的“这里有怪物”。

所以我很惊讶这不起作用吗?一点也不。我实际上更惊讶它甚至是对话框中的一个选项。可能 SQL CE 的设备版本和 PC 版本不同,正是这种差异导致桌面无法正确读取删除文件。或者它可能只是一个错误的连接(再次,请参阅“ActiveSync”)。

那么你如何前进呢?简单的。将数据库从设备复制到 PC,然后使用 Studio 打开 PC 副本。严重地。我就是这样做的,而且效果很好。

我想我之前已经向你推荐过这个,但值得重复。避免使用数据表。它们是巨大的记忆猪,在 CE 下你买不起记忆猪。基本上,它会为您将整个源表复制到 RAM 中。SqlCeDataReader 和 SqlCeResultSet 是你的朋友。

于 2013-12-06T15:17:22.073 回答