Smart Client 离线数据


Smart Client 我想大家都知道吧,它是Microsoft 最近推出的一种将 B/S 和 C/S 结合在一起的一种技术,叫智能客户端。
在 Smart Client 中有很多新的技术,离线数据就是其中之一,对于离线数据操作我们可以有很多方法,如:
数据库同步、隔离存储区、消息队列

数据库同步要求在客户端也安装个应用数据库并保持与服务器应用数据库同步

隔离存储区就是运用Smart Client的新技术在客户端单独开辟一块空间用来存储离线状态下的数据
需要添加引用
usingSystem.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() 方法
从消息中获取相应的信息,就可以对系统进行下一步操作了

优质内容筛选与推荐>>
1、可靠性测试用例设计
2、保证消息可靠性传输以及幂等性
3、阶段1 语言基础+高级_1-3-Java语言高级_03-常用API第二部分_第3节 Calendar类_2_Calendar类的常用成员方法
4、解决HTTP status code is not handled or not allowed
5、模板管理类


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号