黎波

Windows Mobile Development for Line of Business
posts - 182, comments - 1185, trackbacks - 43, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

一、场景描述
在智能设备(Smart Device)应用程序和智能客户端(Smart Client)应用程序的部署阶段,我们需要对离线数据进行初始化,即将后台数据库服务器中的一些数据,导入到离线数据库中。通常采用两种方式对离线数据进行初始化,第一种是在程序第一次运行时,通过数据同步的方式,把数据从后台下载下来;第二种是将预先准备好的离线数据随应用程序一起部署。

对于 SQL Server Compact Edition (SQL CE 3.1) 数据库,第一种方式通常可以利用 Remote Data Access (RDA), Merge Replication, Sync Services for ADO.NET (SQL CE 3.5 中新增) 或者自己实现基于 Web Service 的数据同步机制来实现。RDA 和 Merge Replication 最大的缺点是只能连到 SQL Server 数据库,如果 SQL CE 需要跟 Oracle 和 DB2 等数据库进行数据同步,需要 SQL Server 做“中介”。另外,RDA 没有冲突处理机制,并且每次必须重新下载全部数据;Merge Replication 配置太繁琐了。Sync Services for ADO.NET 目前还在 beta 阶段,beta1 还不支持智能设备应用程序,只支持桌面应用程序。Orcas beta2 刚刚发布,目前还没有下载完毕,不知道有没有性能方面的提升和增加对智能设备应用程序的支持。暂时先对 Sync Services for ADO.NET 保留意见,等我用上 beta2 了再详细介绍。自己实现基于 Web Service 的数据同步机制需要考虑大数据量如何分批次传输和性能问题。总的来说,第一种方式的实现途径很多,如果初始化数据量比较大,并且客户端数量比较多的话,那么将有可能带来漫长的部署过程和一笔巨大的无线网络流量的费用。

第二种方式可以利用 SQL CE 3.1 对桌面应用程序的支持,预先将 SQL Server, Oracle, DB2, MySQL 等等各种数据库的数据导入到 SQL CE 中,然后通过 ActiveSync 批量将 SQL CE 的数据库文件(*.sdf)拷贝到设备或机器上。以后客户端再通过 Web Service 的方式下载新增/修改/删除的数据来更新本地的离线数据。这样可以节约大量的部署时间和网络通信成本。

当然并不是第二种方式一定比第一种方式好,这个看具体的实施环境。本文主要介绍的是第二种方式。

二、技术选择

既然 SQL CE 3.1 支持桌面应用程序,那么我们可以通过三种方式来准备离线数据:第一,利用 RDA 数据同步;第二,利用 Merge Replication 数据同步;第三,用 ADO.NET 直接从读写数据。第一和第二种方式需要额外的安装和配置,而且只支持 SQL Server 数据库。如果非要在第一和第二种方式中选择的话,我会选择 RDA,因为它配置工作量更少,性能更好,更加灵活。本文选择第三种方式,因为它离两个数据库的距离最近,而且支持多种数据库。

三、实现原理

数据导入程序实现起来很简单,不过需要考虑性能。从源数据库读取数据要考虑速度和内存冲击,可以采用 DataSet 或者 DataReader,毫无疑问我们选择 DataReader。将数据写入 SQL CE,通常大家会想到编写一个 SqlCeCommand,然后给 SqlCeCommand 的 CommandText 属性赋上 Insert SQL 语句“insert into Products values(@ProductID, @ProductName)”,接着一边读取数据,一边给参数赋值并写入 SQL CE 数据库中……大家冷落了一个叫 SqlCeResultSet 的对象,它是 SQL Mobile 增加的数据访问对象。SqlCeResultSet 提供了一个功能的组合:DataSet 的可更新性和可滚动性以及与 SqlCeDataReader 类似的性能。SqlCeResultSet 类继承了 SqlCeDataReader 类,因此它拥有 SqlCeDataReader 类所有的特性。利用 SqlCeResultSet 可以实现高性能的数据读取和写入。

四、代码和分析

/// <summary>
/// 将源数据库表的数据复制到 SQL Server Compact Edition 数据库的表中。
/// </summary>
/// <param name="srcConnection">源数据库连接接对象。</param>
/// <param name="destConnection">目标 SQL Server Compact Edition 数据库连接对象。</param>
/// <param name="queryString">源数据的查询语句。</param>
/// <param name="destTableName">目标数据库表名称。</param>
/// <remarks>本方法假设目标 SQL Server Compact Edition 数据库的表已经存在。</remarks>
public static void CopyTable(
    IDbConnection srcConnection, 
    SqlCeConnection destConnection, 
    
string queryString, 
    
string destTableName)
{
    IDbCommand srcCommand 
= srcConnection.CreateCommand();
    srcCommand.CommandText 
= queryString;

    SqlCeCommand destCommand 
= destConnection.CreateCommand();
    destCommand.CommandType 
= CommandType.TableDirect; //基于表的访问,性能更好
    destCommand.CommandText = destTableName;
    
try
    {
        IDataReader srcReader 
= srcCommand.ExecuteReader();

        SqlCeResultSet resultSet 
= destCommand.ExecuteResultSet(
            ResultSetOptions.Sensitive 
|   //检测对数据源所做的更改
            ResultSetOptions.Scrollable |  //可以向前或向后滚动
            ResultSetOptions.Updatable); //允许更新数据

        
object[] values;
        SqlCeUpdatableRecord record;
        
while (srcReader.Read())
        {
            
// 从源数据库表读取记录
            values = new object[srcReader.FieldCount];
            srcReader.GetValues(values);

            
// 把记录写入到目标数据库表
            record = resultSet.CreateRecord();
            record.SetValues(values);
            resultSet.Insert(record);
        }

        srcReader.Close();
        resultSet.Close();
    }
    
catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.ToString());
    }
}

由于 CopyTable 函数的源数据库连接参数采用的是 IDbConnection 接口,所以该方法可以支持多种源数据库。代码中还利用 IDataReader.GetValues(object[] values) 和 SqlCeUpdatableRecord.SetValues(object[] values) 更方便的读取和写入数据。

在使用 CopyTable 函数之前必须预先创建好 SQL CE 数据库的表结构,并且 SQL CE 数据库的表结构必须跟 queryString 参数(select SQL 语句)的查询结果的表结构对应。

通过下面的代码使用 CopyTable 函数:

// 创建源 SQL Server 数据库连接对象
string srcConnString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True";
SqlConnection srcConnection 
= new SqlConnection(srcConnString);

// 创建目标 SQL Server Compact Edition 数据库连接对象
string destConnString = @"Data Source=C:\Northwind.sdf";
SqlCeConnection destConnection 
= new SqlCeConnection(destConnString);

VerifyDatabaseExists(destConnString); //创建数据库结构

srcConnection.Open();
destConnection.Open();

// 复制数据
CopyTable(srcConnection, destConnection, "SELECT * FROM Products""Products");
CopyTable(srcConnection, destConnection, 
"SELECT * FROM Employees""Employees"
);

srcConnection.Close();
destConnection.Close();

五、创建数据库结构

上面说到在使用 CopyTable 函数之前 SQL CE 数据库必须存在并且表结构都创建好。我们现在就来编写创建数据库结构的代码。首先创建一个名为 DbSchema.sql 的文件,并编写 Northwind 数据库中的 Products 和 Employees 表的创建脚本:

CREATE TABLE Products(
    ProductID 
int NOT NULL CONSTRAINT PK_Products PRIMARY KEY,
    ProductName 
nvarchar(40NOT NULL,
    SupplierID 
int NULL,
    CategoryID 
int NULL,
    QuantityPerUnit 
nvarchar(20NULL,
    UnitPrice 
money NULL,
    UnitsInStock 
smallint NULL,
    UnitsOnOrder 
smallint NULL,
    ReorderLevel 
smallint NULL,
    Discontinued 
bit NOT NULL
)
GO
CREATE TABLE Employees(
    EmployeeID 
int NOT NULL CONSTRAINT PK_Employees PRIMARY KEY,
    LastName 
nvarchar(20NOT NULL,
    FirstName 
nvarchar(10NOT NULL,
    Title 
nvarchar(30NULL,
    TitleOfCourtesy 
nvarchar(25NULL,
    BirthDate 
datetime NULL,
    HireDate 
datetime NULL,
    Address 
nvarchar(60NULL,
    City 
nvarchar(15NULL,
    Region 
nvarchar(15NULL,
    PostalCode 
nvarchar(10NULL,
    Country 
nvarchar(15NULL,
    HomePhone 
nvarchar(24NULL,
    Extension 
nvarchar(4NULL,
    Photo 
image NULL,
    Notes 
ntext NULL,
    ReportsTo 
int NULL,
    PhotoPath 
nvarchar(255NULL
)
GO

这段 SQL 语句不能直接在 SQL CE 上执行的,我们需要进行一些字符串的处理。现在将该文件添加到 Visual Studio 2005 的项目资源中。





并添加执行这段 SQL 创建数据库表结构的方法:

public static void VerifyDatabaseExists(string connectionString)
{
    
using (SqlCeConnection connection = new SqlCeConnection(connectionString))
    {
        
if (! File.Exists(connection.Database))
        {
            
using (SqlCeEngine engine = new SqlCeEngine(connection.ConnectionString))
            {
                engine.CreateDatabase();

                
string[] commands = Properties.Resources.DbSchema.Split(
                    
new string[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);

                SqlCeCommand command 
= new SqlCeCommand();
                command.Connection 
= connection;
                connection.Open();
                
for (int i = 0; i < commands.Length; i++)
                {
                    command.CommandText 
= commands[i];
                    command.ExecuteNonQuery();
                }
            }
        }
    }
}

六、总结

性能测试的结果会因为环境的不同而有一些出入,我想留给大家去做会更有意义。不过我相信这是当前性能比较好的向 SQL CE 导入数据的方法之一。目前需要预先创建好 SQL CE 的表结构是美中不足的地方,我会在后续文章中实现一个自动根据查询结果生成创建 SQL CE 表结构的 SQL 语句的代码,其实并不难。

参考:
ADO.NET Generic Copy Table Data Function
Creating your SQL Server Compact Edition database and schema in code

示例代码下载:sqlce_data_import.rar

作者:黎波
博客:http://upto.cnblogs.com/
日期:2007年7月29日

Feedback

#1楼    回复  引用  查看    

2007-07-30 22:52 by 小桥流水      
我曾经也和你一样,将数据库的数据导入到 SQL CE 中,然后通过 ActiveSync 批量将 SQL CE 的数据库文件(*.sdf)拷贝到设备或机器上。
感觉这样数据速度也比较快,编程也简单。但是在程序PC端安装时,需要安装SqlSupport.msi文件客户端才支持SQL CE 数据库文件的操作。

#2楼 [楼主]   回复  引用  查看    

2007-07-31 00:25 by 黎波      
@小桥流水
SqlSupport.msi 文件是哪里来的?SQL CE 3.1 是可以通过xcopy 部署的吧?

#3楼    回复  引用  查看    

2007-07-31 22:45 by 小桥流水      
如果只在机子上安装.net framework2.0,System.Data.SqlServerCe.dll这个命名空间下的东西不能用。

#4楼 [楼主]   回复  引用  查看    

2007-08-01 02:26 by 黎波      
@小桥流水
我只在smart device项目中使用sqlce,还没有注意到有这个问题...

#5楼    回复  引用  查看    

2007-08-02 16:30 by newr2006      
写得很好,多谢了.

#6楼    回复  引用    

2007-08-03 09:07 by yy [未注册用户]
为什么varchar用你的这个程序会不行?

#7楼    回复  引用  查看    

2007-08-03 09:25 by 黎波      
@yy
因为 sqlce 不支持 varchar/char/text 数据类型,只支持nvarchar/nchar/ntext 类型,所以你要在 sqlce 的数据库创建脚本修改相关的字段类型。
请参考:http://msdn2.microsoft.com/zh-cn/library/ms172424.aspx

#8楼    回复  引用    

2007-08-03 12:02 by yy [未注册用户]
SQLCommand出现Exception,为什么会出现{" [ 7,2,, ]"}?是什么意思

#9楼    回复  引用    

2007-08-03 12:08 by yy [未注册用户]
我只是把你的SQL换成
CREATE TABLE DHL_LABELLING_REPORT_RESULT (
ITEM_NO nvarchar(20) NOT NULL ,
STORER_RECEIPT_ID nvarchar(10) NOT NULL ,
CARTON_SSCC nvarchar(30) NOT NULL ,
CARTON_EPC nvarchar(50) NULL ,
CARTON_EPC_HEX nvarchar(50) NULL ,
GOOD_QUANTITY int NULL ,
DAMAGE_QUANTITY int NULL
)
GO
之后就有Exception了

#10楼    回复  引用    

2007-08-03 13:45 by yy [未注册用户]
发现你的程序问题了,你的分割符是"GO",刚好字段还有"GO"两个字母就报错了,问题解决了

#11楼    回复  引用  查看    

2007-08-03 13:57 by 黎波      
@yy
呵呵,可以换成其他符号,如分号(';'),反正有源码可以自己改。
谢谢你发现这个bug!

#12楼    回复  引用    

2007-08-08 16:07 by LGhua [未注册用户]
上例的SouceConnection连接的是SQL Server数据库么?
如果这个程序在PPC上跑得话, 是否可以连接的就是远程PC上的SQL Server数据库,就像SQL Server Client端一样,直接操作PC上的SQL Server?(或者Oracle数据库。。。 )

如果可以,用你的方法就真是太方便了!

#13楼 [楼主]   回复  引用  查看    

2007-08-08 20:18 by 黎波      
@LGhua
.NET CF是支持直接访问SQL Server的,但是Oracle不行。

#14楼    回复  引用    

2007-08-15 13:31 by 犇牛牛 [未注册用户]
不大清楚你的这个数据拷贝代码应该如何演示,我是新建了一个smart phone console application cf2.0 的工程,然后debug的时候在srcConnection.Open();这个地方报错,也没说原因,就是sqlexception错误
看output好像是什么文件没找到异常.

因为debug的时候还是启用了模拟器,我不知道是不是不能连接到本地的数据库,比较模拟器和本地数据库之间没有通讯。那你的这段代码是如何将本地数据库的数据拷贝到sqlce的sdf数据库呢?请详细的讲解一下,我是新手:)

#15楼    回复  引用  查看    

2007-08-15 13:41 by 黎波      
@犇牛牛
你可以下载示例代码进行调试,这个程序是在桌面运行的,如果你想直接在设备导入数据,可以参考续文:http://www.cnblogs.com/upto/archive/2007/08/08/sqlce-data-import-2.html

#16楼    回复  引用    

2007-10-23 16:16 by hxh [未注册用户]
当ppc离线的情况下如何实现sql mobile 和其他数据库同步?

#17楼 [楼主]   回复  引用  查看    

2007-10-23 22:56 by 黎波      
@hxh
既然离线了,也就是说访问不了网络,那怎么连接到其他PC呢?

#18楼    回复  引用    

2007-10-29 15:43 by netabc [未注册用户]
请问为什么一直报错
有关调用实时(JIT)调试而不是此对话框的详细信息,
请参见此消息的结尾。

************** 异常文本 **************
System.DllNotFoundException: 无法加载 DLL“sqlceme30.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
在 System.Data.SqlServerCe.NativeMethods.DllAddRef()
在 System.Data.SqlServerCe.SqlCeConnection..ctor()
在 System.Data.SqlServerCe.SqlCeConnection..ctor(String connectionString)
在 InitDvAsset.Form1.buttonDownload_Click(Object sender, EventArgs e) 位置 D:\work\InitDvAsset\InitDvAsset\InitDvAsset\Form1.cs:行号 32
在 System.Windows.Forms.Control.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
在 System.Windows.Forms.Button.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

#19楼 [楼主]   回复  引用  查看    

2007-10-29 21:38 by 黎波      
@netabc
根据错误提示诊断为设备没有安装SQL CE。

#20楼    回复  引用    

2007-10-30 09:23 by fyt234 [未注册用户]
谢谢博主的文章
我现在用SQLCE2.0+SQLServer2000开发一个应用,有15—30个左右用户,采用复制合并,在数据同步的时候,如果数据量稍微大一点,就要同步30-50分钟,是不是SQL CE不适合做这种应用?

#21楼    回复  引用    

2007-11-19 09:16 by tdskee [未注册用户]
为什么按你的做后,提示:StringSplitOptions.RemoveEmptyEntries报错,
上下文不存在StringSplitOptions...什么回事???

#22楼 [楼主]   回复  引用  查看    

2007-11-19 17:25 by 黎波      
@tdskee
StringSplitOptions 枚举在.NET完整版才支持,.NET CF版不支持。

#23楼    回复  引用    

2007-11-23 13:17 by tdskee [未注册用户]
@黎波
我是在装有vs2003的环境下又装了vs2005的.这个难道有什么地方发生冲突了吗?
不知道你做过,直接从oracle中把数据写到sdf文件中呢?
vs03上面可以操作实现吗?

#24楼 [楼主]   回复  引用  查看    

2007-11-23 13:36 by 黎波      
@tdskee
我现在就是从Oracle导入数据到sql server compact,在台式机上。
vs03不支持这种方法,因为sql server compact要.net 2.0/.net cf 2.0以上支持。

#25楼    回复  引用    

2007-12-02 22:19 by tdskee [未注册用户]
--引用--------------------------------------------------
黎波: @netabc
根据错误提示诊断为设备没有安装SQL CE。
--------------------------------------------------------
我再pc上确实装了sqlce30,但是还是报那样的错,你回复netabc的时候,说:设备没有安装sqlce,怎么和设备拉上关系了呢?这个程序是在pc端运行的,和pda什么的都没联系的对吧???

#26楼    回复  引用    

2007-12-07 17:16 by fyt234 [未注册用户]
--引用--------------------------------------------------
fyt234: 谢谢博主的文章
我现在用SQLCE2.0+SQLServer2000开发一个应用,有15—30个左右用户,采用复制合并,在数据同步的时候,如果数据量稍微大一点,就要同步30-50分钟,是不是SQL CE不适合做这种应用?
--------------------------------------------------------
劳烦博主解释一下吧,谢谢了先。
我们后台的数据库是Oracle9i,现在是先用自己写的同步程序同步数据到SQL Server2000,再同步到PDA上,离线作业后再导回来。现在用户一多,离线时间稍微长点,同步时就要很长时间。不知道是不是SQL Server 2000的性能就是这样?改版到2005可以提高性能吗?

#27楼 [楼主]   回复  引用  查看    

2007-12-10 21:11 by 黎波      
@tdskee
不好意思,当时没有看清楚,因为我第二篇文章是直接从Mobile设备导入SQL Server数据的。
应该是PC上没有安装SQL Server Compact Edition v3.1

#28楼 [楼主]   回复  引用  查看    

2007-12-10 21:17 by 黎波      
@fyt234
你要用工具监控到底瓶颈在哪里?
是PDA与服务器之间的网络传输速度?还是IIS服务器压力过大?还是发布服务器压力过大?还是Oracle同步数据到SQL Server慢?
分析好了原因,就好办了,合并复制可以搭建多层,不过比较复杂!

#29楼    回复  引用    

2007-12-11 15:20 by bazooka [未注册用户]
在创建目标 SQL Server Compact Edition 数据库连接对象的时候,SqlCeConnection destConnection = new SqlCeConnection(destConnString);这一句提示“试图加载格式不正确的程序”,该怎么解决啊

#30楼 [楼主]   回复  引用  查看    

2007-12-11 20:46 by 黎波      
@bazooka
没有遇到过这个错误!检查一下你安装 SQL Server CE版本或引用的DLL是否正确?

#31楼    回复  引用    

2007-12-14 10:40 by fyt234 [未注册用户]
@黎波
谢谢楼主,我们主要是PDA同步回去的时候很慢。我观察了一下,PDA上点击同步后,很快就可以在服务器上SQLServer复制合并记录列表里面看到处理了多少多少条记录,然后就是很漫长很漫长的等待,PDA上才能出来同步成功提示。我们是百兆内网,服务器上IIS只是运行我们的复制合并,数据库是单独的服务器。

#32楼 [楼主]   回复  引用  查看    

2007-12-16 13:45 by 黎波      
@fyt234
合并复制默认是双向同步的,可以通过设置SqlCeReplication.ExchangeType为ExchangeType.Upload,实现只上传。这样可能对提高速度有帮助。

#33楼    回复  引用    

2007-12-17 10:40 by fyt234 [未注册用户]
谢谢博主
我们用的是CE2.0,EVC开发,业务需要先下载数据,在PDA上修改,再同步回去。CE2.0上好像定义复制合并的功能很弱,只能简单的调用。下载了CE3.0来测试,在EVC中编译可以通过,在PDA上运行时,CoCreateInstance(CLSID_SQLSERVERCE_3_0,...)就报错。用VS2005编译出它自带的northwindoledb工程和CE3.0自带的查询器都可以在PDA上运行成功。博主有没有EVC上的可以成功编译运行的经验?

#34楼    回复  引用    

2007-12-21 00:42 by 杨永发 [未注册用户]
CE5.0 开发 MC1770C50B模拟器下的程序,没有framework,以及SQL CE想直接访问SERVER上的数据库 sqlserver2005,如何解决??

#35楼 [楼主]   回复  引用  查看    

2007-12-21 08:02 by 黎波      
@杨永发
安装.net cf和sql client,然后就可以访问了。

#36楼    回复  引用    

2007-12-24 10:41 by xkx12 [未注册用户]
请问在pc上创建ce数据库,需要什么前提条件吗?
windows应用程序怎么无法加载system.data.sqlceclient文件
请指点!

#37楼    回复  引用    

2007-12-24 10:43 by xkx12 [未注册用户]
上面的system.data.sqlceclient文件
应该是system.data.sqlserverce文件 是我写错了

#38楼 [楼主]   回复  引用  查看    

2007-12-24 11:40 by 黎波      
@xkx12
需要在PC上安装SQL Server Compact Edition,可以到这里找到下载地址:
http://www.cnblogs.com/upto/archive/2007/03/13/672953.aspx

#39楼    回复  引用    

2007-12-24 13:17 by xkx12 [未注册用户]
未能加载文件或程序集“System.Data.SqlServerCe, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
这是什么原因呢?请指教!

#40楼    回复  引用    

2007-12-24 16:34 by wince4.2 [未注册用户]
你的示例用ce2.0可以吗

#41楼 [楼主]   回复  引用  查看    

2007-12-24 21:08 by 黎波      
@wince4.2
不可以。

#42楼    回复  引用    

2007-12-25 10:25 by wince4.2 [未注册用户]
你的示例能不能部署到wince4.2系统上

#43楼    回复  引用    

2007-12-29 09:44 by songzhaoyi [未注册用户]
你好
我用直连sqlserver后,.open()的时候出现:
我用的就是下载的例子
未处理 System.Data.SqlClient.SqlException
Message="SqlException"
Class=20
LineNumber=0
Number=11
Procedure="ConnectionRead (recv())."
Server="D0504"
Source=".Net SqlClient Data Provider"
State=0
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError()
at System.Data.SqlClient.SqlInternalConnection.OnError()
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.ReadNetlib()
at System.Data.SqlClient.TdsParser.ReadBuffer()
at System.Data.SqlClient.TdsParser.ReadByte()
at System.Data.SqlClient.TdsParser.Run()
at System.Data.SqlClient.TdsParser.Run()
at System.Data.SqlClient.SqlInternalConnection.Login()
at System.Data.SqlClient.SqlInternalConnection.OpenAndLogin()
at System.Data.SqlClient.SqlInternalConnection..ctor()
at System.Data.SqlClient.SqlConnection.Open()
at CopyTableMobileDemo.Form1.button1_Click()
at System.Windows.Forms.Control.OnClick()
at System.Windows.Forms.Button.OnClick()
at System.Windows.Forms.ButtonBase.WnProc()
at System.Windows.Forms.Control._InternalWnProc()
at Microsoft.AGL.Forms.EVL.EnterMainLoop()
at System.Windows.Forms.Application.Run()
at CopyTableMobileDemo.Program.Main()

#44楼 [楼主]   回复  引用  查看    

2007-12-30 21:17 by 黎波      
@songzhaoyi
感觉是SQL语句或存储过程有问题。

#45楼    回复  引用    

2008-01-15 11:40 by xuce [未注册用户]
楼主您好!
请问我现在不用RDA,但是PDA上还是用SQL MOBILE和总数据库是ORACLE的情况下,什么样的同步解决方案是最好的??

#46楼 [楼主]   回复  引用  查看    

2008-01-15 11:48 by 黎波      
@xuce
最好是用Web Service来实现数据同步,这样就不会依赖于数据库的类型。
实现的方法你可以参考 TaskVision Mobile 版本,它用的是DataSet的方法,比较简单。如果你需要实现复杂的数据同步方案,可以研究这个网站的内容:http://www.syncguru.com/

#47楼    回复  引用    

2008-01-26 11:45 by dde [未注册用户]
建议看看这篇文章对你会有帮助的 http://www.150it.cn/bianchengwendang/VC/13990148130169.html

#48楼    回复  引用    

2008-02-19 14:27 by guthing [未注册用户]
按照楼主的方法已经将数据导入,估计是数据库当初建立的时候没有设置其大小,默认为128M,现在数据量很大,原数据库的容量大小满足不了要求了,有什么办法能改变原来数据库的大小吗?还请赐教!

#49楼 [楼主]   回复  引用  查看    

2008-02-19 15:32 by 黎波      
@guthing
只要在ConnectionString增加Max Database Size选项,设置相应的大小即可,最大值为4096(4G)。

SqlCeConnection conn = new SqlCeConnection();
conn.ConnectionString = @"Data Source = 'SalesData.sdf';Max Database Size = 256";
conn.Open();

参考:
http://technet.microsoft.com/zh-cn/library/ms171771.aspx

#50楼    回复  引用    

2008-02-20 10:07 by guthing [未注册用户]
我按照您的说法做了,现在导入数据可以超过128M,但数据量超过256M时又出现未指定错误了。我用的连接字符串如下:
string connStr = "Persist Security Info = False; Data Source = TCMT.sdf;Temp File Max Size = 512;Max Database Size =512; Max Buffer Size = 2048";是不是这个串的原因。
如果您有时间的话能不能加我的QQ:277756884,帮我指点一下!

#51楼    回复  引用    

2008-02-20 14:27 by guthing [未注册用户]
目前问题已经得到解决,就不麻烦楼主了谢谢!

#52楼    回复  引用    

2008-02-28 15:29 by hnrpc [未注册用户]
远程访问SQL,服务器上要不要开端口1433

#53楼    回复  引用    

2008-02-28 15:30 by hnrpc [未注册用户]
也就是说,用你这个代码访问服务器(PC机)上的SQL的话,服务器要不要开放1433端口呢

#54楼 [楼主]   回复  引用  查看    

2008-02-28 15:42 by 黎波      
@hnrpc
当然需要

#55楼    回复  引用    

2008-03-07 11:30 by hnrpc [未注册用户]
这几天都在做这个东西,还是有点小问题,conn.open()的时候,报错:"PlatformNotSupportedException",
连接字 符串"server=220.221.151.100,2433;database=test;uid=sa;pwd=sa;";
程序是在模拟器(模拟器可以上网)上运行上,"220.221.151.100是远程服务器,确定2433(把1433改成了2433)开放,望LZ指点一下,

#56楼 [楼主]   回复  引用  查看    

2008-03-07 14:14 by 黎波      
@hnrpc
我也曾遇到过这种错误信息。如果你的SQL Server服务器是简体中文的操作系统,而你的Pocket PC是非简体中文的操作系统,就会有这个问题。原因是SQL Server数据库的排序规则跟SQL Server CE数据库的不一致,要把它们改成相同就可以了。这可能是SqlClient的bug。

#57楼    回复  引用    

2008-03-07 17:55 by hnrpc [未注册用户]
谢谢LZ,换个中文模拟器搞定,最近对移动开发很感兴趣,不知道LZ有没有好的教材书推荐一下

#58楼 [楼主]   回复  引用  查看    

2008-03-07 19:06 by 黎波      
@hnrpc
如果是入门,我建议下载MSDN Webcast看。
书的话我是推荐《.NET精简框架程序设计:C#版》

#59楼    回复  引用    

2008-03-07 20:43 by 侯志刚 [未注册用户]
楼主请问:我用VS2005创建一个数据库在模拟器上好用,可是当平台换成WINCE5.0板子的时候,提示"无法找到 PInvoke DLL“sqlceme30.dll”
我该怎么解决呢?谢谢啊.

#60楼    回复  引用    

2008-03-07 20:53 by 侯志刚 [未注册用户]
楼主请问:我用VS2005环境下,创建一个数据库在模拟器上创建成功,可是当平台换成WINCE5.0板子的时候,提示"无法找到 PInvoke DLL“sqlceme30.dll”
我该怎么解决呢?谢谢啊.(我将sqlceme30.dll已经复制到应用程序的目录下).

#61楼    回复  引用    

2008-03-07 21:02 by 侯志刚 [未注册用户]
是不是在WINCE5.0的板子上也需要安装SQL Server Compact Edition,
因为,我直接在板子上手动创建数据库,也创建失败,系统给出的错误提示为
"Failed to initialize the provider. please make sure that SQL Server Compact Edition is properly installed "
谢谢楼主啊

#62楼    回复  引用    

2008-03-07 21:37 by 侯志刚 [未注册用户]
sqlce30.wce5.armv4i.CAB
* sqlce30.dev.ENU.wce5.armv4i.CAB
* sqlce30.repl.wce5.armv4i.CAB
到WinCE5.0中,然后分别安装,都提示安装成功。
但还是不行,请帮帮我,谢谢

#63楼    回复  引用    

2008-03-08 08:32 by guthing [未注册用户]
从sql2005向sqlCe中导入数据的时候用你说的方法速度确实很快,我现在想从sqlCe或者其他(sql2005、oracle)类型的数据库中将数据导入到sql2005中有没有效率比较高的方法,下面是我做的一个方法(sqlCe数据导入到sql2005),测试后发现速度十分的慢。
/// <summary>
/// 将源数据库表的数据复制到 SQL Server 2005 数据库的表中
/// </summary>
/// <param name="srcConnection">源数据库连接</param>
/// <param name="destConnection">sql server 2005数据库连接(oleDB)</param>
/// <param name="queryString">源数据表的查询语句</param>
/// <param name="destTableName">目标数据表的名称</param>
public void CopyTableToSqlServer(
IDbConnection srcConnection,
OleDbConnection destConnection,
string queryString,
string destTableName
)
{
IDbCommand srcCommand = srcConnection.CreateCommand();
srcCommand.CommandType = CommandType.Text;
srcCommand.CommandText = queryString;

OleDbCommand destCommand = destConnection.CreateCommand();
destCommand.CommandType = CommandType.TableDirect;
destCommand.CommandText = destTableName;
OleDbDataAdapter da = new OleDbDataAdapter(destCommand);
OleDbCommandBuilder builder = new OleDbCommandBuilder(da);

DataSet ds = new DataSet();
da.Fill(ds);
IDataReader srcReader = srcCommand.ExecuteReader();

object[] values;
while(srcReader.Read())
{
//从源数据库中读出一行数据
values = new object[srcReader.FieldCount];
srcReader.GetValues(values);

DataRow row = ds.Tables[0].NewRow();
row.ItemArray = values;
ds.Tables[0].Rows.Add(row);
da.Update(ds.Tables[0]);
}

srcReader.Close();

}

#64楼    回复  引用    

2008-03-09 16:13 by wws [未注册用户]
博主您好:
我的程序原来是VS2003(CF1.0)的,用到了RDA(SQL CE2.0与SQL Server2000进行远程同步),调试运行良好。现在我想用VS2005(CF2.0)继续开发,对原来程序升级到CF2.0了,但RDA却又不行了,老是报错,而且每次还报的不一样,有时报:
Error Code:80072F76
Message:内部错误:传输消息中的Http标头信息已坏或缺失。可能是网络传输错误或IIS问题。
Minor Err:28035
但大部分情况下是出错误对话框,说“Unable to create database”,应该是dbEngine.CreateDatabase()时出的错。怎么回事呢?难道是SQL CE2.0在CF2.0下没法用?升级到CF2.0后必须改用SQL Server Mobile(也就是Sqlce3.0)与SQLServer2000同步才行?
附我的RDA代码,在CF1.0下运行一切正常:
if(File.Exists(strDBFile))
{
File.Delete(strDBFile);
}
SqlCeEngine dbEngine = new SqlCeEngine();
dbEngine.LocalConnectionString = strConnLocal;
try
{
dbEngine.CreateDatabase();
}
catch (SqlCeException exSQL)
{
MessageBox.Show("Unable to create database" + exSQL.Errors[0].Message);
}

SqlCeRemoteDataAccess rdaNW = new SqlCeRemoteDataAccess();
try
{
rdaNW.LocalConnectionString = strConnLocal;
rdaNW.InternetUrl = strURL;
rdaNW.InternetLogin = "";
rdaNW.InternetProxyPassword = "";
rdaNW.Pull("patient", "SELECT * FROM patient", strConnRemote, RdaTrackOption.TrackingOnWithIndexes, "ErrorDoctor");
MessageBox.Show("获取数据成功!");
}
catch(SqlCeException exSQL)
{
Errors.ShowErrors(exSQL);
}
finally
{
rdaNW.Dispose();
}

#65楼 [楼主]   回复  引用  查看    

2008-03-09 16:36 by 黎波      
@侯志刚
从错误信息看是SQLCE没有安装好。
你检查一下sqlceme30.dll等文件是否已经存在\Windows目录下,并确认的安装的SQLCE版本的硬件平台是否跟你的板的平台一致。

#66楼 [楼主]   回复  引用  查看    

2008-03-09 16:40 by 黎波      
@guthing
改成这样试一试:
object[] values;
while(srcReader.Read())
{
//从源数据库中读出一行数据
values = new object[srcReader.FieldCount];
srcReader.GetValues(values);

DataRow row = ds.Tables[0].NewRow();
row.ItemArray = values;
ds.Tables[0].Rows.Add(row);
}
da.Update(ds.Tables[0]);

/*慢的原因主要是:DataAdapter.Update() 语句每次执行都要打开和关闭数据库连接,这个操作是最耗资源的,除非你设置了连接池。*/

#67楼 [楼主]   回复  引用  查看