[CSHARP-710] Implement PreSerialize hook on objects Created: 22/Mar/13 Updated: 11/Mar/19 Resolved: 26/Mar/13 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | Vladimir Perevalov | Assignee: | Unassigned |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
All |
||
| Description |
|
Bson serialization allow objects to implement ISupportInitialize I tried to implement IBsonSerializable and inside do my stuff and just call BsonSerializer.Seriaze(). But that obviuously caused stack overflow Also, I just don't like doing such hacky customization. Code would be much easier to understand with appropriate interface/method names. |
| Comments |
| Comment by Vladimir Perevalov [ 27/Mar/13 ] | |||||||||||||||||||||||||||||||
|
Here are some more detailed test results. First of all I'll describe my records and data. Here's my class for record: public Dictionary<long, HashSet<long>> ReadArticleIds { get; set; } } Following are results for different serialization schemes (numbers are operations per second: BinFormatterGzip write: 46,5 read: 208,6 Names should be selfexplanatory (I used just serializer and serializer+compressor, Native means no special serializers - driver default). | |||||||||||||||||||||||||||||||
| Comment by Craig Wilson [ 26/Mar/13 ] | |||||||||||||||||||||||||||||||
|
I think that is a great solution to cross-platform compatibility. Our "Binary" type is just that, a bunch of bytes. We have special subtypes for UUIDS and MD5, but the general subtype is arbitrary and can hold any type of data. So standardizing your format on protocol buffers is perfectly fine and is cross-platform compatible. I'm fairly certain that protocol buffers requires "compile time" support because it's binary format is not self-describing. In other words, it isn't dynamic schema compatible because it requires both parties to know the format of the messages. Anyways, thanks for the suggestion. I'm going to close this ticket as "Works as Designed." | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 26/Mar/13 ] | |||||||||||||||||||||||||||||||
|
No problem with driver | |||||||||||||||||||||||||||||||
| Comment by Craig Wilson [ 26/Mar/13 ] | |||||||||||||||||||||||||||||||
|
Vladimir, | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 26/Mar/13 ] | |||||||||||||||||||||||||||||||
|
By the way, it is easy to make this thing multiplatform, if you use some open standard for binary serialization like Google Protocol Buffers. | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 26/Mar/13 ] | |||||||||||||||||||||||||||||||
|
Robert, your approach seem to work quite fine. Thanks again for the tip! | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
I understand this. For now this is not a problem. | |||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
You're welcome. One other observation worth making about storing your data this way is that applications written with other platforms/languages/drivers will not be able to use this data since it is just a binary BLOB in the database and only .NET knows how to deal with that binary BLOB. | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
It looks really good, but I have to test it. I'll post my results probably next week. | |||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
Here's how you could choose to serialize your array of integers using the BinaryFormatter in the current version of the driver: Declare your class like this:
And write this short custom serializer:
When writing a custom serializer you implement Serialize and Deserialize (instead of BeforeSerialize and AfterSerialize in your proposed IBsonSerializationHook) with the additional advantage that you don't have to add a temporary field like ABlob that isn't really needed. Also, a custom serializer can be used in many places, so if you had other classes that also had large integer arrays you could use the same custom serializer with them instead of having to implement IBonSerializationHook all over again for every class with a large integer aray. Would an approach like this meet your needs? | |||||||||||||||||||||||||||||||
| Comment by Vladimir Perevalov [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
Ok, maybe I missed correct number. Here's my sample code: public class C : ISupportInitialize [BsonIgnore] public int[] A { get; set; } public BsonBinaryData ABlob {get;set;} static BinaryFormatter f = new BinaryFormatter(); public void EndInit() { if (ABlob == null) return; var ms = new MemoryStream(ABlob.Bytes); A = (int[])f.Deserialize(ms); } public void BeginInit() { } You only have to call Serialize before inserting into mongo. | |||||||||||||||||||||||||||||||
| Comment by Robert Stam [ 22/Mar/13 ] | |||||||||||||||||||||||||||||||
|
I am unable to reproduce your claim that deserialization takes more than a second. When I serialize the following class with 10000 elements:
This is how long it took on my machine:
|