Smart Client 我想大家都知道吧,它是Microsoft 最近推出的一种将 B/S 和 C/S 结合在一起的一种技术,叫智能客户端。
在 Smart Client 中有很多新的技术,离线数据就是其中之一,对于离线数据操作我们可以有很多方法,如:
数据库同步、隔离存储区、消息队列
数据库同步要求在客户端也安装个应用数据库并保持与服务器应用数据库同步
隔离存储区就是运用Smart Client的新技术在客户端单独开辟一块空间用来存储离线状态下的数据
需要添加引用
using System.IO;
using System.IO.IsolatedStorage; // 该命名空间下的类均是对隔离存储区进行操作的
对隔离存储区的操作如下 CacheHelper 类
class CacheHelper
{
public static void WriteDataSetToIsolatedStorage(DataSet data, string fileName)
{
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForAssembly(); // 获取与调用代码的程序集标识对应的用户范围的独立存储
// IsolatedStorageFileStream 公开独立存储中的文件
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(fileName, FileMode.Create, isoStore))
{
using (StreamWriter writer = new StreamWriter(isoStream))
{
data.WriteXml(writer, XmlWriteMode.DiffGram);
}
}
}
public static void ReadDataSetFromIsolatedStorage(DataSet data, string fileName)
{
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForAssembly();
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(fileName, FileMode.Open, isoStore))
{
using (StreamReader reader = new StreamReader(isoStream))
{
data.ReadXml(reader, XmlReadMode.DiffGram);
}
}
}
}
在提交数据前还要检测网络是否联接,这就需要添加其他引用
using System.Net;
using System.Net.NetworkInformation;
具体的判断是否网络联接代码如下
private void OnAddressChanged(object sender, EventArgs e)
{
bool connected = IsOnline();
if (InvokeRequired)
{
// 此处是个委托
SetStatus del = delegate(bool status)
{
UpdateStatus(status);
};
Invoke(del, new object[] { connected });
}
else
{
UpdateStatus(connected);
}
}
private void UpdateStatus(bool connected)
{
if (connected)
{
………………
}
else
{
………………
}
}
private bool IsOnline()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties properties = adapter.GetIPProperties();
if (adapter.OperationalStatus != OperationalStatus.Up) // 判断网络是否连接
{
continue;
}
UnicastIPAddressInformationCollection addressCollection = properties.UnicastAddresses; // 获取此连接的单播地址
foreach (UnicastIPAddressInformation addressInfo in addressCollection)
{
if (IPAddress.IsLoopback(addressInfo.Address)) // 是否本地地址 如 127.0.0.1
{
continue;
}
if (addressInfo.Address.ToString() == IPAddress.IPv6None.ToString())
{
continue;
}
if (addressInfo.ToString() == IPAddress.None.ToString())
{
continue;
}
return true;
}
}
return false;
}
delegate void SetStatus(bool status);
在网络正常联接时,你可以安部就班的做正常应该做的操作
如果没联接则要调用 CacheHelper 的方法对隔离存储区进行操作,也就
WriteDataSetToIsolatedStorage 和 ReadDataSetFromIsolatedStorage 方法
至于消息队列,要求客户端和服务器端都添加了“消息队列”这一Windows 组件
在应用程序中需要引用 System.Messaging;这一命名空间
然后在向服务器提交时创建一个消息队列
MessageQueue mq = new MessageQueue("s1p3\\MQTest", false, true);
MessageQueue 类有6个构造函数,我这只是用了其中的一种
"s1p3\\MQTest" 指的是该消息队列将要发送到哪里
消息队列大致可以分为3种类型,1 公共队列 2 专用队列 3 日志队列
这3种队列的写法也有所区别
公共队列 MachineName\QueueName
专用队列 MachineName\Private$\QueueName
日志队列 MachineName\QueueName\Journal$
MachineName 表示你要发送给哪台计算机,如果是本机 MachineName 可以用点号“.”
QueueName 表示该计算机中的队列名称
Private$ 和 Journal$ 是固定的,无需要更改
程序中常用到的也就是 “公共队列”和“专用队列”,而且其中又以“专用队列”占绝大多数
消息队列有了,接下来就要涉及到消息了
我从很多资料上看到都要用到 System.Messaging.Message 类(注:不是 System.Windows.Forms.Message 类,要注意区分)
一般都是这样写的
System.Messaging.Message m = new System.Messaging.Message();
然后就是设置 Message 的属性,
如 MessageName.body = ojbect;
MessageName.Formatter = ……
………………
最后 MessageQueueName.Send(MessageName);
如果你仔细点,就会注意到 MessageQueue 类的 Send() 方法里要求的参数是一个 object
所以我就尝试了一下把我要发送的内容直接当作参数,一试果然成功
当然这只是一种比较省事的做法,相对应的对该内容的一些属性参考就要被忽略了
当 Send() 完毕后记得把消息队列关闭哦
MessageQueueName.Close();
如果网络通的话,消息队列会自动发送
如果网络不通的话,消息队列会保存在客户端,等到网络重新联接时消息队列会自动发送
消息发送完了,就要在服务器端去接收了
获得消息的方法有几种
GetAllMessage()
Receive() 等
我们从 GetAllMessage() 字面上不难看出该方法是获取所有的消息队列
而 Receive() 只是对单个消息获取
在实际应用中 GetAllMessage() 方法更切实际点
MessageQueue mq = new MessageQueue(".\\MQTest");
mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(object) });
如果需要知道 Message 的一些属性需要添加以下代码,否则会有错误报出
mq.MessageReadPropertyFilter.SourceMachine = true;
mq.MessageReadPropertyFilter.Body = true;
下面就获取所有的消息队列吧
try
{
System.Messaging.Message [] mss = mq.GetAllMessages(); // 获取消息队列中的所有消息
foreach (System.Messaging.Message ms in mss) // 循环所有的消息
{
mq.Receive();
………………
}
}
catch
{
}
如果用 GetAllMessage() 方法的话,记得在每次获取单个消息后调用 Receive() 方法
从消息中获取相应的信息,就可以对系统进行下一步操作了