7

我正在使用 ServiceStack.OrmLite 将数据保存在SQLite数据库中,到目前为止我对此非常满意。

但是,我的许多对象都具有复杂类型的属性,我不想使用JSV.

我需要能够指定应该用于将属性存储在数据库中的自定义序列化/反序列化(作为字符串)。在db4o世界上这相当于使用IObjectConstructor.

无法正确序列化和反序列化的复杂类型的一个很好的例子是 NodaTime 类型,即使它们可以很容易地映射到字符串(我已经有了与 一起使用的序列化/反序列化函数db4o)。

实现这一目标的最简单方法是什么?包装器不是很方便,因为我必须为包含这种复杂类型的属性的每种类型编写和维护一个包装器。

4

3 回答 3

6

对于那些可能对我目前用于使用 OrmLite 实现自定义序列化的包装器模式感兴趣的人(也可以与其他 ORM 一起使用),这是一个简单的工作示例,NodaTime其中包含未正确序列化的类型:

public class BusinessObject {
    public class Poco {
        public readonly BusinessObject BusinessObject;

        public Poco(BusinessObject businessObject) {
            this.BusinessObject = businessObject;
        }

        public Poco() {
            this.BusinessObject = new BusinessObject();
        }

        public string Id {
            get { return this.BusinessObject.Id; }
            set { this.BusinessObject.Id = value; }
        }

        public decimal Amount {
            get { return this.BusinessObject.Amount; }
            set { this.BusinessObject.Amount = value; }
        }

        public DateTime Dt {
            get { return this.BusinessObject.Dt.ToDateTime(); }
            set { this.BusinessObject.Dt = LocalDateTime.FromDateTime(value).Date; }
        }

        public string TimeZone {
            get { return this.BusinessObject.TimeZone.Id; }
            set { this.BusinessObject.TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(value); }
        }

        public string Description {
            get { return this.BusinessObject.Description; }
            set { this.BusinessObject.Description = value; }
        }
    }

    public string Id { get; private set; }
    public decimal Amount { get; private set; }
    public LocalDate Dt { get; private set; }
    public DateTimeZone TimeZone { get; private set; }
    public string Description { get; private set; }

    public BusinessObject() { }

    public BusinessObject(string id, decimal amount, LocalDate dt, DateTimeZone timeZone, string description) {
        this.Id = id;
        this.Amount = amount;
        this.Dt = dt;
        this.TimeZone = timeZone;
        this.Description = description;
    }
}

我希望很快可以为应该使用自定义代码处理的特定类型定义挂钩/回调,并且 OrmLite 将允许从持久性中重新加载具有私有设置器的属性(目前它只能在一个方向上工作)。

更新 (2014/03/08):作为一种临时解决方法,可以让 OrmLite 通过首先调用来使用自定义序列化/反序列化:

JsConfig<BusinessObject>.TreatValueAsRefType = true;

即使BusinessObject是引用类型。然后,您可以享受以下的美丽/简单/无处不在:

JsConfig<BusinessObject>.RawSerializeFn = bo => bo.Serialize();
JsConfig<BusinessObject>.RawDeserializeFn = str => BusinessObject.Deserialize(str);

希望很快会添加对自定义映射的支持(例如,可以将 NodaTime.LocalDate 映射到 DateTime 而不是字符串)。

于 2013-11-02T13:30:45.580 回答
2

要序列化复杂类型,请在以下位置设置您自己的序列化器(和反序列化器)JsConfig

JsConfig<Foo>.SerializeFn = foo => foo.ToString("XOXO", CultureInfo.InvariantCulture);
JsConfig<Foo>.DeSerializeFn = foo =>
{
    var result = Foo.Parse(foo, CultureInfo.InvariantCulture);
    return result;
};

您可能还想告诉 JsConfig 假设 UTC 日期:

JsConfig.Init(new Config {
    JsConfig.AssumeUtc = true
});
于 2013-11-27T12:37:01.927 回答
2

OrmLite现在支持可插入的文本序列化器。

可插入序列化允许您为每个可用的 RDBMS 提供程序指定不同的复杂类型序列化策略,例如:

//ServiceStack's JSON and JSV Format
SqliteDialect.Provider.StringSerializer = new JsvStringSerializer();       
PostgreSqlDialect.Provider.StringSerializer = new JsonStringSerializer();
//.NET's XML and JSON DataContract serializers
SqlServerDialect.Provider.StringSerializer = new DataContractSerializer();
MySqlDialect.Provider.StringSerializer = new JsonDataContractSerializer();
//.NET XmlSerializer
OracleDialect.Provider.StringSerializer = new XmlSerializableSerializer();

您还可以通过实现 IStringSerializer来提供自定义序列化策略:

public interface IStringSerializer
{
    To DeserializeFromString<To>(string serializedText);
    object DeserializeFromString(string serializedText, Type type);
    string SerializeToString<TFrom>(TFrom from);
}
于 2013-11-01T06:19:33.493 回答