How to set BsonDateTime Serializer default options in C# - c#

I need to store DateTime in MongoDb with the same precission as in .NET DateTime. I found this solution:
[BsonDateTimeOptions(Representation = BsonType.Document)]
public DateTime RequestedTime
... to use attributes and BsonDocument type to store also Ticks property of .NET DateTime.
The thing is
I don't want to do this for every DateTime
I don't want to have Mongo reference in my Domain.
I found this post and this sof question which propose to use DateTimeSerializer as
DateTimeSerializationOptions options = new DateTimeSerializationOptions(DateTimeKind.Utc, BsonType.Document);
var serializer = new DateTimeSerializer(options);
BsonSerializer.RegisterSerializer(typeof(DateTime), serializer);
But the hell I'm not able to find out where should I do this. Startup? Program? Which package do I need to have access to BsonDateTimeOptions class as I cannot see it anywhere. Is it possible to set it outside of the assembly where affected properties are stored (aka drifting it away from Domain?)
I'm using GridFS Driver instead of classical mongo, is this the problem?

Related

How can I turn UTC Timezone off for MongoDB

I'm using the extension below for MongoDB date fields because of MongoDB stores times in UTC by default.
public static class DateTimeExtensions {
public static DateTime AdjustUtcDiffByOffset(this DateTime time) {
return time.AddHours(DateTimeOffset.Now.Offset.Hours);
}
}
}
All of them cause different problems although I have tried a few ways like attributes or serialization methods in .NET on the application level. I have decided to use this extension in .NET for now but I think that this is not a complete and exact solution too.
Is there any solution for this problem on the database level without being dependent on programming language wtih an adjust or something else?
EDIT
I think that I should an explain more after comments below. I already know MongoDB stores times in UTC that linked in this post as you see above. This can be useful but I don't need any UTC time zone difference in my app and I don't want to deal in Presentation Layer for every programming language separately. And also, I don't even want only one extra row or function in the other layers because of move away than base logic or business.
Let the my architecture undertaking this. I'm pretty lazy, the life is really short and the birds are flying outside :) I don't want the different fields as like as string convertings unnecessarily. I need a datetime type in the db due to I'm doing many time calculation in the app.
I'm using .NET now and therefore MongoDB .NET driver. I have tried different serialization methods but it cause another problems in the Data Access architecture. In conclusion, I can use UTC in my another app but I don't want it now and I prefer the local time when I assign to the field. I have decided to use the encapsulation below for C# especially.
private DateTime _startTime;
public DateTime StartTime {
get => _startTime;
set => _startTime = new DateTime(value.Ticks, DateTimeKind.Utc);
}
I don't think it's possible from the db level. What I did, was to write custom setter for date properties which will force mongoDB to assume the time is already in UTC, thus avoid a conversion like below:
private DateTime _createdUTC;
public DateTime CreatedUtc
{
get
{
return _createdUTC;
}
set
{
_createdUTC = new DateTime(value.Ticks, DateTimeKind.Utc);
}
}
MongoDB always saves dates in UTC.
What you can do is indicate to the client that he must convert the date to the local date when retrieving data from the database.
You can register a serializer before instantiating the client:
BsonSerializer.RegisterSerializer(DateTimeSerializer.LocalInstance);
var client = new MongoClient(options) ...

EF, How to save/retrieve TimeSpan as other data type?

SQLCe doesn't support TimeSpan, so I need to save this in some other way. Is it possible to define somewhere a default conversion, like in the DbContext, or would I need to handle this manually in the repositories? I don't like to change my entity classes just because of this.
Btw, I only save TimeSpan of < 24h.
Example would be great if there are some neat tricks.
I know you say you don't want to modify your entities, but if you're using code first this would be pretty simple to do by modifying your entities :)
You could define a property that isn't mapped into the database, that uses another property as its backing store. In this example, TickCount would get saved in the database, but everything else could access Span which exposes TickCount as a TimeSpan struct.
public long TickCount { get; set; }
[NotMapped]
public TimeSpan Span {
get {
return new TimeSpan(TickCount);
}
set {
TickCount = value.Ticks;
}
}
Pretty old but in case anyone ever needs this, I have cloned and modified System.Data.SQLite in order to support TimeSpan properties (mapped to sqlite TIME columns)
You can find the source at https://github.com/arielflashner/System.Data.SQLite
Well, it seems this is basically NOT POSSIBLE.
A TimeSpan property must be marked NotMapped, or by fluent Ignore (then saved as per Steve's answer).
At least that's my understanding now.
EF does not support type mapping or type conversion..
https://stackoverflow.com/a/12053328
Btw, NHibernate maps TimeSpan to integer by default, when using SqLite. No conversions or tricks needed there. Not sure about other databases.

How to read old version of MongoDb document with new model in code

Lets say my c# model updated while correspondent collection still contains old documents, I want old and new documents to coexist in the collection, while using only new version of c# model to read them. I wish no inheritance is used if possible. So I wonder which of this issues are solvable and how:
there is a new property in c# model which does not present in database. I think it never should be an issue, Mongo knows nothing about it, and it will be initialized with default value. The only issue here is to initialize it with particular value for all old documents, anybody knows how?
one of property has gone from model. I want MongoDb to find out there is no more property in c# class to map the field of old document to, and to ignore it instead of crashing. This scenario probably sounds a bit strange as it would mean some garbage left in database, but anyway, is the behavior possible to implement/configure?
type if changed, new type is convertible to old one, like integer->string. Is there any way to configure mapping for old docs?
I can consider using inheritance for second case if it is not solvable otherwise
Most of the answers to your questions are found here.
BsonDefaultValue("abc") attribute on properties to handle values not present in the database, and to give them a default value upon deserialization
BsonIgnoreExtraElements attribute on the class to ignore extra elements found during deserialization (to avoid the exception)
A custom serializer is required to handle if the type of a member is changed, or you need to write an upgrade script to fix the data. It would probably be easier to leave the int on load, and save to a string as needed. (That will mean that you'll need a new property name for the string version of the property.)

Equivalent datatype to TBXML for C#

Is there any similar datatype that I can use to save data in C# in the same way it is saved in TBXML Objective C?
Googling TBXML shows an XML parser. If this is the case, C# does have XML-parsing capabilities in the System.Xml namespace.
You can store (virtually) any datatype using XmlSerializer see http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
You can specify whether a property of an object is to be stored using property attributes otherwise the serializer will use reflection to store the whole object.
See http://www.codeproject.com/Articles/14064/Using-the-XmlSerializer-Attributes for a decent tutorial

Serialize c# DateTime to Java Time and Java Date for SAP webservice

I need to upload data to SAP via a webservice, using WCF in c# 4.0 (VS2010). I have been able to connect and post data to the using the webservice successfully, however i ran into a problem with date and time.
I have an class called MtrRdngDocERPRsltCrteReqRslt having 2 fields called ActualMeterReadingDate and ActualMeterReadingTime. When Visual Studio generated the proxy class, it converted these objects as datetime objects, however I know they are Date and Time on the other end of the webservice (which is implemented in JAVA).
The problem is that when I pass datetime values to these fields, they are not getting serialized and are not being received on the other end.
Also note that when i serialize dates that are defined as DateTime by the webservice, these work perfectly.
I have also used the following code to serialize the whole object and save it locally as xml on and I have the same problem.
public void SerializeToXML(MeterReadingUploadWS2.MtrRdngDocERPRsltBulkCrteReqMsg bb, string path)
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(bb.GetType());
var serializer = new System.Xml.Serialization.XmlSerializer(bb.GetType());
using (var writer = System.Xml.XmlWriter.Create(path))
{
serializer.Serialize(writer, bb);
}
}
I had some troubles doing that some time ago, and I decided to work with long properties, because it's the closest generic interop way to achieve it, since c#'s DateTime and java's Date objects are different things from different languages.

Categories

Resources