SPB-设计机制-序列化字段

来自站长百科
跳转至: 导航、​ 搜索

导航: 上一页


在产品的不断完善过程中或者二次开发过程中,经常需要对现有的对象增加新的属性。通常情况下,为了应对这些变化需要在数据库的相应表中预留字段(当然不预留字段就需要修改数据库中的表、修改相应的存储过程或sql语句、修改数据访问层…),然后在使用时赋予具体的含义。

这样做最常见的一个结果就是使数据库中的一些字段异常混乱。

SpaceBuilder中,我们针对这种需求使用了序列化字段,下面介绍数据序列化的原理及如何使用数据序列化。

一、数据库的存储格式

在数据库中的存储格式如下图所示,所有需要序列化的数据全部存储到PropertyNames(存储属性名称及PropertyValues中对应的存储位置)、PropertyValues(存储属性的具体数据)两个字段中。

先分析一下存储的数据,首先是PropertyNames字段 “EnableRatings:S:0:4:EnableTrackBacks:S:4:4:CommentModerationType:S:8:4:” ,“EnableRatings”其实是在实体类中定义的一个属性名称,“:”表示定义完毕,“S:0:4”表示在PropertyValues字段中的字符从0开始后面4位属于“EnableRatings”的属性值,同理:“S:4:4”表示,从第四个字符开始,后面5个表示“EnableTrackBacks”的属性值,依次类推可以获得PropertyNames所有的字段的值。(其中S代表存储格式是字符串,由于目前全部以字符串存储所以不需特别关注)。

这样我们就利用PropertyNames、PropertyValues两个字段存储任意多个数据项,而且不用对操作数据库的存储过程或sql语句做任何更改,这就为SpaceBuilder的数据序列化奠定了数据存储基础。

Spacebuilder091.jpg

设计参考

借鉴了asp.net 2.0的Profile。Profile的功能是管理用户个人资料,而用户个人资料在不同的项目中会有不同的需求(比如:年龄、性别、兴趣、爱好、毕业院校…),而Profile作为一个通用的功能必须满足这些具体的需求,它同样采取了类似的数据存储结构,如下图所示。

Profile采用了3个字段对扩展属性进行存储:

  1. PropertyNames同样存储属性名称及在PropertyValuesString或PropertyValuesBinary中的相应数据的存储位置,并以S及B确定数据是以字符串形式还是二进制形式存储;
  2. PropertyValuesString存储属性的字符串数据;
  3. PropertyValuesBinary存储属性的二进制数据;

Spacebuilder092.jpg

当然Profile为了做到更加容易对Profile扩展新的属性,还支持在web.config中通过配置文件来增加新属性。

二、如何使用数列化数据

  • 首先确保需要使用序列化字段的实体类从SpaceBuilder.Common.ExtendedAttributes派生。

例如:User,如下图所示:

Spacebuilder093.jpg

ExtendedAttributes主要方法如下:

Spacebuilder094.jpg

在ExtendedAttributes的派生类我们可以方便的通过GetBool、GetInt、GetDouble、GetString、GetExtendedAttribute<T>获取相应的属性值。GetSerializerData、SetSerializerData一般用于把对象存储到数据库,或从数据库取出数据并生成对象的过程使用(参见2)。

例如,我们可以定义AvatarUrl序列化属性,该属性的代码如下:


/// <summary>
        /// 用户头像文件名称
        /// </summary>
        public string AvatarUrl
        {
            get { return GetExtendedAttribute("avatarUrl"); }
            set { SetExtendedAttribute("avatarUrl", value); }
       }	
  • 在数据库的表中增加PropertyNames、PropertyValues两个字段,一般设置PropertyNames、PropertyValues的类型为ntext。

进行对象持久化时(即存储到数据库),需要编写如下代码:


     SerializerData data = user.GetSerializerData();
      myCommand.Parameters.Add("@PropertyNames", SqlDbType.NText).Value = data.Keys;
      myCommand.Parameters.Add("@PropertyValues", SqlDbType.NText).Value = data.Values;

从数据库取出数据生成对象时,一般需要编写如下代码:

SerializerData data = new SerializerData();
            if (dr["PropertyNames"] == DBNull.Value)
                data.Keys = "";
            else
                data.Keys = dr["PropertyNames"] as string;

            if (dr["PropertyValues"] == DBNull.Value)
                data.Values = "";
            else
                data.Values = dr["PropertyValues"] as string;
user.SetSerializerData(data);


参考资料[ ]