Elfocrash / Cosmonaut

🌐 A supercharged Azure CosmosDB .NET SDK with ORM support
https://cosmonaut.readthedocs.io
MIT License
342 stars 44 forks source link

CosmosResponse.Entity does not match saved object from ResourceResponse #84

Closed keymatic closed 4 years ago

keymatic commented 5 years ago

Hello.

Thank you for all your hard work.

I'm trying to use JsonSerializerSettings to format dates in objects saved to CosmosDB. Here is an example console application code:

public class Program
    {
        public static async Task Main(string[] args)
        {
            Console.WriteLine("Adding new article...");
            var cosmosSettings = new CosmosStoreSettings("database", "endpoint",
                "key",
                settings =>
                {
                    settings.JsonSerializerSettings = new JsonSerializerSettings()
                    {
                        DateTimeZoneHandling = DateTimeZoneHandling.Utc, //always use Z not offset
                        DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ" // use only 3 decimals
                    };
                });
            var store = new CosmosStore<Article>(cosmosSettings, "News");
            var entity = new Article() { Id = "1", Title = "Hello world", CreatedDate = DateTime.UtcNow };

            // add new article
            var addedResponse = await store.AddAsync(entity);
            // get entity from CosmosResponse
            var addedEntity = addedResponse.Entity;
            // get entity from CosmosResponse.ResourceResponse
            var expectedEntity =
                JsonConvert.DeserializeObject<Article>(addedResponse.ResourceResponse.Resource.ToString());

            // note that string representation contains 7 decimals
            Console.WriteLine("Date to be saved: " + entity.CreatedDate.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"));
            // note that string representation contains 7 decimals
            Console.WriteLine("Entity.CreatedDate: " + addedEntity.CreatedDate.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"));
            // note that string representation contains 7 decimals
            Console.WriteLine("Date actually saved: " + expectedEntity.CreatedDate.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"));
        }
    }

here is the output:

Date to be saved: 2019-05-10T07:26:25.5620443Z

Entity.CreatedDate: 2019-05-10T07:26:25.5620443Z

Date actually saved: 2019-05-10T07:26:25.5620000Z

The goal here is to store only 3 decimals in date field. I would expected addedResponse.Entity object to have only 3 decimals in date field but according to output it has 7 decimals. If you get the saved object from CosmosResponse.ResourceResponse it contains 3 decimals as expected.

Is it an expected behavior that CosmosResponse.Entity is the object "to be saved" but not "actually saved"?

Elfocrash commented 5 years ago

Hello @keymatic

Yes the idea is that the Entity property is the object to be saved, not the one that you saved. The idea behind it is that if cosmos fails, you still have your object in the failed response to add some custom retry logic.

Originally I was thinking that I could check the status code and then replace it with the returned resource but I rejected this idea because this would involve json deserialisation which would slow down the response.

I will add something in the docs and the property summary to make that clear.

Elfocrash commented 4 years ago

This is now fixed on the latest version. Closing.