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 . . .
TreatValueAsRefType = true
and setting bothSerializeFn
andRawSerializeFn
, the property is still persisted with CurrentCulture (commas for decimals) and not with my InvariantCulture version (dots). – BookstandRawDeserializeFn
does not exist. But that is not a problem, since theSerializeFn
is hit without problems. – BookstandServiceStack.OrmLite.PostgreSQL
instead of ServiceStack.OrmLite.Sqlite.Mono. Maybe that is it. – Bookstand