Details
-
Bug
-
Status: Closed
-
Major - P3
-
Resolution: Works as Designed
-
None
-
None
-
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); |
}
|
}
|
}}
|
|