-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Serialization
-
Labels:None
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); } } }}