NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。

整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。

开源地址:https://github.com/NewLifeX/X (求star, 864+)

 

XCode是充血模型,在实体类上附带有大量便捷操作,其中就包括各种目标数据类型的导入导出!

 

Json序列化 

 当下最常用的数据通信格式毋容置疑肯定是Json,实体对象可直接转Json作为接口返回值。

下面看看一个普通Role实体对象的Json序列化(ToJson)和Json反序列化(ToJsonEntity)的例程和效果。

如上,Role实体对象可通过ToJson转为json字符串,并通过ToJsonEntity把字符串转为另一个Role实体对象。

在XCode v9.0之前,实体基类Entity直接带有ToJson/FromJson。后来因为Json实在太常用了,提升为全局扩展方法。

 

Json作为最通用的数据传输格式(没有之一),ToJson直接扩展Object,有三个参数:是否换行缩进、是否写空值、是否驼峰命名

上文示例中的ToJson(true, false, false)表示采用换行缩进(可读性更好),不写空值(整数的0和字符串的null等),不适用驼峰命名。

  

Xml序列化

 Xml作为曾经的数据传输格式之王,仍然有相当一部分古老接口使用。

ToXml/ToXmlEntity 也是全局扩展方法,其中参数可以控制序列化为普通Xml或者Xml属性。

从结果来看,Xml可读性非常好,但是占用空间很大,一般比Json还要大一截。

 

二进制序列化

 XCode序列化的绝招是二进制序列化,能够让实体对象和二进制数据互相转换,更小、更快!

序列化同样的实体对象,只需要39字节,远小于Json和Xml,并且速度更快(不需要字符串分割操作)。

实体对象没有ToBinary之类的快速方法,而是需要先转化为IAccessor接口,然后Write序列化为数据流,或者Read读取数据流。

数据流是个好东西,最常用的有内存流、文件流、网络流、加密流、压缩流,等等等。

文件流FileStream,可以让实体对象保存为文件,或者文件加载为实体对象,(借助文件缓存实体数据?);

网络流NetworkStream,可以让实体对象在网络中传输;

 

IAccessor 访问器接口,可实现任意对象到数据流的读写访问。

NewLife.Redis 优先支持 IAccessor 接口,因此,把XCode实体对象写入Redis时,采用的是二进制高效精简格式,而不是默认的Json格式

 

实体类可通过重载 OnWrite 来自定义二进制序列化的行为。


/// <summary>二进制序列化到数据流</summary>
/// <param name="stream">数据流</param>
/// <param name="context">上下文</param>
/// <param name="extend">是否序列化扩展属性</param>
protected virtual Boolean OnWrite(Stream stream, Object context, Boolean extend)
{
    var bn = context as Binary;
    if (bn == null) bn = new Binary
    {
        Stream = stream,
        EncodeInt = true
    };

    var fs = extend ? Meta.AllFields : Meta.Fields;
    foreach (var fi in fs)
    {
        bn.Write(this[fi.Name], fi.Type);
    }

    return true;
}

从上面代码可以看出,只是调用二进制序列化Binary来把各个数据字段写入流中。

 

看到这里,你是不是有很多可以大干一场的想法?别急,这只是开胃菜,还有更好的。

 

示例中看到,二进制序列化最大缺点是可读性极差!一般只能看到其中部分字符串。

 

实体列表存储

 单个实体对象的二进制序列化只适用于简单场合,如写入Redis,实际工程级应用,多以实体列表为主。

实体列表存储以扩展方法提供:

  • Write,写入实体列表到数据流
  • Read,从数据流加载实体列表
  • SaveFile,保存实体列表到文件(可用作数据缓存)
  • LoadFile,从文件加载实体列表

以上示例演示了具有4个对象的角色列表如果读写数据流以及文件。

 

有朋友要问,能否借助实体列表读写文件的功能,实现某些数据表的本地化缓存,即使数据库宕机,仍然能够继续提供服务?

答案显然是可以的,并且我在实际工作中也经常这么干。

 

数据分析中经常需要用到几十上百台服务器进行分析计算,应用启动时必须把配置数据和常用基础数据一次性载入内存,例如几万行的网点数据;

如果几十个节点同时启动向数据库请求网点数据,数据库将不堪重负变得非常缓慢,影响计算应用的加载甚至可能导致出错退出;

这种场景,可以在加载一次后,把实体列表数据保存到本地文件中,然后定时(10分钟)更新;

下次启动时,直接使用本地缓存数据,大大提升了应用启动速度,并且降低了数据库负担;

 

Csv导入导出

 Csv格式常用于办公室Excel数据传递,以及数据库数据导入导出等。

XCode支持百万级导出!内部 CsvFile 支持流式读写,一边构造一边写入文件,而不是一次性在内存生成好再写入!

 

魔方的 Excel导出、Csv导出、Json导出、Xml导出等功能,都由 XCode 实现!

 

作者:大石头 发布:2020-03-20 21:56:57 浏览:2,877)