让ORMLite使用适当的结构系列化 [英] Make ORMLite use proper serialization for structs

查看:191
本文介绍了让ORMLite使用适当的结构系列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;博士:



我注册一个串行器和一个struct结果
串行器和解串器不叫,但解串器。 ,是



我怎样才能解决这个结果
它的工作原理上正确引用类型,做 JsConfig<位置取代。 。TreatValueAsRefType = TRUE; 并没有帮助






龙版本:



我储存使用ORMLite两种复杂类型:位置(一个结构,从外部库DotSpatial我们不控制)和元组



为了要能够妥善保存/从数据库中读取它们,我定义自己的串行器和解串器:

  //结构。由position.ToJsv()调用,而不是由ORMLite的connection.Insert称为()。 
JsConfig<地位与GT; .SerializeFn =位置=>
{
字符串str = position.ToString(NULL,CultureInfo.InvariantCulture);
返回海峡; //断点在这里。
};
//结构体。所谓的两个。
JsConfig<地位与GT; .DeSerializeFn =位置=> Position.Parse(位置,CultureInfo.InvariantCulture);

//引用类型。工作正常。
JsConfig<元组LT;双层,双>> .SerializeFn =元组=>的String.Format(CultureInfo.InvariantCulture,
{0} {1} {2},
tuple.Item1,CultureInfo.InvariantCulture.TextInfo.ListSeparator,tuple.Item2
);
//工作正常了。
JsConfig<元组LT;双层,双>> .DeSerializeFn =元组=>
{
VAR值= tuple.Split(新[] {} CultureInfo.InvariantCulture.TextInfo.ListSeparator,StringSplitOptions.None);
双击项目1,ITEM2;
如果(values.Length == 2
和;&安培; double.TryParse(值[0],出ITEM1)
和;&安培; double.TryParse(值[1],出ITEM2))
{
VAR的结果=新的记录<双层,双>(ITEM1,ITEM2);
返回结果;
}
抛出新的ArgumentException(无法解析东坐标和北从数据库;的malformatted?,元组);
};



调试



一个突破点T>(项目=> item.Foo ==吧)结果$ b $ connection.Where<:从DB与ORMLite阅读时解串器被击中 connection.Insert(项目)


$ b $:在串行b中的突破点写入数据库与ORMLite时不打b

我想也许串行器没有被正确注册,所以我叫 .ToJsv()的对象。

  VAR纬度= Latitude.Parse(00°00'02.7451\N,CultureInfo.InvariantCulture); 
VAR LON = Longitude.Parse(013 °29'17.3270\WCultureInfo.InvariantCulture);
位置POS =新的位置(纬度,经度);
串富= pos.ToJsv(); //作品,命中断点。

当击中断点,海峡= 00°00'02.7451N, 013°29'17.3270W 。结果
但是随着ORMLite插入时,断点打不到,我在数据库中保存的值,如 00° 00'02,7451N,013°29'17,3270:W - 注意逗号,由于文化



该数据库保存文化有关的价值观! (



尝试



由于出现这种情况只有在结构,我试图注册类型被视为。引用类型,但是这似乎并没有工作。

  JsConfig<位置> .TreatValueAsRefType = TRUE; 



更新:



我使用的 ORMLite。 PostgreSQL的的NuGet包(五70年3月9日)。它包括ServiceStack.Text(v 70年3月9日)和Npgsql(v 2.0.11)。



我想尝试获取来自源控件的代码,直接调试它,但现在我没有时间。



位置结构在外部库,我不能改变定义。



简约样品



我必须在 https://gist.github.com/aneves/7830776 上传极简样本,其显示以下的输出:

 的事情,目前的文化:12,6; 10,9 
的东西,不变的文化: 12.6,10.9
的东西,从JSV:12,6; 10,9
>>反序列化10; 35
>>无法分析的价值,它的格式不正确。 (10; 35)
发现这一点:盒[A:0; 0]
按任意键继续。 。 。


解决方案

更新:



OrmLite 的源代码后上GitHub上,似乎:




  • JsConfig<位置> .TreatValueAsRefType 从不序列化数据到数据库时进行检查。

  • 对于反序列化OrmLite会的总是拨打 TypeSerializer.DeserializeFromString ,这就是为什么您的方案在那个方向努力只有



要解决这个问题,我已经提交的补丁到主存储库。在此同时欢迎你们要么重新编译使用OrmLite这个补丁,或者干脆使用重新编译版本(基于4.0.3),我已经为您提供的这里代替从的NuGet相应的文件之一。



我希望此修复程序将被纳入。在接下来的正式发布,同时在3 *分支



原来的答复:



如果您在位置结构控制的ToString(这似乎不是这样),你尝试重写()? OrmLite应该调用它,如果我没记错的话:

 结构位置{
公共重写的ToString(对象o,CultureInfo的文化) {
/ *您系列化* /
}

公共重写的ToString(){//将OrmLite用于序列化
position.ToString(NULL,CultureInfo的.InvariantCulture);
}
}



这可能不是解决SerializeFn<>不会被调用,但可够好你的目标,至少要等到错误是固定的。


tl;dr:

I am registering a serializer and a deserializer on a struct.
The serializer is not called, but the deserializer is.

How can I fix this?
It works properly on reference types, and doing JsConfig<Position>.TreatValueAsRefType = true; did not help either.


Long version:

I am storing two complex types using ORMLite: Position (a struct, from external library DotSpatial which we do not control) and Tuple.

In order to be able to properly store/read them from the database, I defined their serializers and deserializers:

// Struct. Called by position.ToJsv(), NOT called by ORMLite's connection.Insert() .
JsConfig<Position>.SerializeFn = position =>
{
    string str = position.ToString(null, CultureInfo.InvariantCulture);
    return str; // Breakpoint here.
};
// Struct. Called in both.
JsConfig<Position>.DeSerializeFn = position => Position.Parse(position, CultureInfo.InvariantCulture);

// Reference type. Works fine.
JsConfig<Tuple<double, double>>.SerializeFn = tuple => string.Format(CultureInfo.InvariantCulture,
    "{0}{1}{2}",
    tuple.Item1, CultureInfo.InvariantCulture.TextInfo.ListSeparator, tuple.Item2
    );
// Works fine too.
JsConfig<Tuple<double, double>>.DeSerializeFn = tuple =>
{
    var values = tuple.Split(new[] { CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
    double item1, item2;
    if (values.Length == 2
        && double.TryParse(values[0], out item1)
        && double.TryParse(values[1], out item2))
    {
        var result = new Tuple<double, double>(item1, item2);
        return result;
    }
    throw new ArgumentException("Could not parse easting and northing from database; malformatted?", "tuple");
};

Debugging

A break-point in the deserializer is hit when reading from the DB with ORMLite: connection.Where<T>(item => item.Foo == bar).
 break-point in the serializer is not hit when writing to the DB with ORMLite: connection.Insert(item).

I thought maybe the serializer was not being registered properly, so I called .ToJsv() on the object.

var lat = Latitude.Parse("00°00'02.7451\"N", CultureInfo.InvariantCulture);
var lon = Longitude.Parse("013°29'17.3270\"W", CultureInfo.InvariantCulture);
Position pos = new Position(lat, lon);
string foo = pos.ToJsv(); // Works, hits the breakpoint.

When hitting the breakpoint, str = 00°00'02.7451"N,013°29'17.3270"W.
But when inserting with ORMLite, the breakpoint is not hit and I get values in the database such as 00°00'02,7451"N;013°29'17,3270"W - note the commas, due to the culture.

The database is saving culture-dependent values! :(

Attempts

Since this happens only on structs, I tried to register the type to be treated as a reference type, but that did not seem to work.

JsConfig<Position>.TreatValueAsRefType = true;

Update:

I am using the ORMLite.PostgreSQL Nuget package (v 3.9.70). It includes ServiceStack.Text (v 3.9.70) and Npgsql (v 2.0.11).

I want to try getting the code from source control and debugging it directly, but for now I don't have time.

The Position struct is defined in an external library, which I cannot change.

Minimalist sample

I have uploaded a minimalist sample at https://gist.github.com/aneves/7830776 , which shows the following output:

Thing, current culture: 12,6;10,9
Thing, invariant culture: 12.6,10.9
Thing, from Jsv: "12,6;10,9"
>> deserializing 10;35
>> Could not parse value, it is malformed. (10;35)
Found this: Box[A: 0;0]
Press any key to continue . . .

解决方案

UPDATE:

After checking the source code of OrmLite on GitHub, it appeared that:

  • JsConfig<Position>.TreatValueAsRefType would never be checked when serializing data into the database.
  • For deserialization OrmLite would always call TypeSerializer.DeserializeFromString, this is why your scenario worked in that direction only.

To fix the issue, I have submitted a patch to the master repository. In the mean time you are most welcome to either recompile OrmLite using this patch, or simply use the recompiled version (based on 4.0.3) I have made available for you here in lieu of one of the corresponding file from NuGet.

I hope this fix will be incorporated in the next official release, and also in the 3.* branch.

ORIGINAL ANSWER:

If you have control over the Position struct (which seems not to be the case), have you tried overriding ToString()? OrmLite should call it if I remember correctly:

struct Position {
    public override ToString(object o, CultureInfo culture) {
        /* Your serialization */
    }

    public override ToString() { // Will be used by OrmLite to serialize
        position.ToString(null, CultureInfo.InvariantCulture);
    }
}

It may not solve SerializeFn<> not being called but could be good enough for your objective, at least until the bug is fixed.

这篇关于让ORMLite使用适当的结构系列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆