Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-2670

Sorting on DateTimeOffset field fails when default (Array) serialization is used

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Works as Designed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Serialization
    • Labels:
      None

      Description

      When sorting on DateTimeOffset field (ascending), the sort fails when default serialization (Array) is used. 

       

      Please find the tests attached below

      using System;
      using System.Linq;
      using System.Linq.Expressions;
      using System.Threading.Tasks;
      using FluentAssertions;
      using MongoDB.Bson;
      using MongoDB.Bson.Serialization.Attributes;
      using MongoDB.Driver;
      using MongoDB.Driver.Core.Events;
      using Xunit;
      using Xunit.Abstractions;namespace MongoDbDateTimeOffset
      {
          public interface IFoo
          {
              Guid Id { get; set; }
              DateTimeOffset DateTimeOffset { get; set; }    }    public class FooString : IFoo
          {
              public Guid Id { get; set; }
              [BsonRepresentation(BsonType.String)]
              public DateTimeOffset DateTimeOffset { get; set; }
          }    public class FooArray : IFoo
          {
              public Guid Id { get; set; }
              [BsonRepresentation(BsonType.Array)]
              public DateTimeOffset DateTimeOffset { get; set; }
          }    public class FooDocument : IFoo
          {
              public Guid Id { get; set; }
              [BsonRepresentation(BsonType.Document)]
              public DateTimeOffset DateTimeOffset { get; set; }
          }    public class MongoDbTests
          {
              private readonly ITestOutputHelper _helper;
              private readonly MongoClient client;        public MongoDbTests(ITestOutputHelper helper)
              {
                  _helper = helper;            client = new MongoClient(new MongoClientSettings()
                  {
                      Server = new MongoServerAddress("localhost"),
                      Credential = MongoCredential.CreateCredential("admin", "mongoadmin", "secret"),
                      ClusterConfigurator = cb =>
                      {
                          cb.Subscribe<CommandStartedEvent>(e =>
                              _helper.WriteLine($"{e.CommandName}: {e.Command.ToJson()}"));
                      }
                  });
              }        private async Task Can_Sort_By_DateTimeOffset<T>(OrderDirection direction) where T : IFoo
              {
                  var collection = client.GetDatabase("foobar").GetCollection<T>(typeof(T).Name.ToLowerInvariant() + "_" + direction.ToString());
                  collection.DeleteMany(FilterDefinition<T>.Empty);            var foos = new[]
                      {
                          new DateTimeOffset(2019, 07, 20, 12, 00, 00, TimeSpan.FromHours(3)),
                          new DateTimeOffset(2019, 07, 21, 12, 00, 00, TimeSpan.FromHours(3)),
                          new DateTimeOffset(2019, 07, 22, 12, 00, 00, TimeSpan.FromHours(3))
                      }
                      .Select(x =>
                      {
                          var foo = Activator.CreateInstance(typeof(T)) as IFoo;
                          foo.DateTimeOffset = x;
                          foo.Id = Guid.NewGuid();
                          return foo;
                      })
                      .Cast<T>()
                      .OrderBy(x => x.Id)
                      .ToArray();            await collection.InsertManyAsync(foos);            // run
                  var query = collection.AsQueryable().OrderBy(x => x.DateTimeOffset, direction)
                      .Select(x => x.DateTimeOffset);
                  var result = query.ToArray();            var expected = foos.AsQueryable().OrderBy(x => x.DateTimeOffset, direction).Select(x => x.DateTimeOffset)
                      .ToArray();            // assert
                  result.Should().Equal(expected);
              }
              [Theory]
              [InlineData(OrderDirection.Ascending)]
              [InlineData(OrderDirection.Descending)]
              public async Task Can_Sort_AsString(OrderDirection direction) =>
                  await Can_Sort_By_DateTimeOffset<FooString>(direction);        [Theory]
              [InlineData(OrderDirection.Ascending)]
              [InlineData(OrderDirection.Descending)]
              public async Task Can_Sort_AsArray(OrderDirection direction) =>
                  await Can_Sort_By_DateTimeOffset<FooArray>(direction);        [Theory]
              [InlineData(OrderDirection.Ascending)]
              [InlineData(OrderDirection.Descending)]
              public async Task Can_Sort_AsDocument(OrderDirection direction) =>
                  await Can_Sort_By_DateTimeOffset<FooDocument>(direction);    }    public enum OrderDirection
          {
              Ascending,
              Descending
          };
          public static class OrderByExtensions
          {
              public static IQueryable<T> OrderBy<T>(this IQueryable<T> queryable, Expression<Func<T, object>> keySelector, OrderDirection direction)
              {
                  switch (direction)
                  {
                      case OrderDirection.Ascending:
                          return queryable.OrderBy(keySelector);                case OrderDirection.Descending:
                          return queryable.OrderByDescending(keySelector);                default:
                          throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
                  }
              }
          }}
      
      

       

        Attachments

          Activity

            People

            Assignee:
            rstam Robert Stam
            Reporter:
            migajek@gmail.com Michał Gajek
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: