Linq to DocumentDB:按日期时间字段筛选

Linq to DocumentDB:按日期时间字段筛选,linq,azure-cosmosdb,Linq,Azure Cosmosdb,我正在使用LINQ来DocumentDB,目前我正试图通过datetime字段过滤返回的记录。我的质询如下: var mycollection = Client.CreateDocumentQuery<Test>(MyCollection.DocumentsLink) .Where(d => d.Time >= DateTime.Now) .AsEnumerable

我正在使用LINQ来DocumentDB,目前我正试图通过datetime字段过滤返回的记录。我的质询如下:

      var mycollection = Client.CreateDocumentQuery<Test>(MyCollection.DocumentsLink)
                        .Where(d => d.Time >= DateTime.Now)
                        .AsEnumerable();

发生此错误是因为我正在使用datetime字段进行筛选。如果我要对任何字符串字段进行过滤,这将非常有效。如何防止此错误?

不支持
DateTime
时间,您必须将
DateTime
转换为int,这样您的JSON如下所示(例如):

您需要使用
JsonConverter
并将
DateTime
属性视为历元。此代码是从中借用的

.ToEpoch
扩展方法定义为:

public static class Extensions
{
    public static int ToEpoch(this DateTime date)
    {
        if (date == null) return int.MinValue;
        DateTime epoch = new DateTime(1970, 1, 1);
        TimeSpan epochTimeSpan = date - epoch;
        return (int)epochTimeSpan.TotalSeconds;
    }
}

DocumentDB中的DateTime对象默认序列化为ISO 8601字符串格式,例如:“2016-08-08T22:10:50.000000 Z”

在这种情况下,您可以使用SQL语法而不是LINQ,因为不支持DateTime对象

请注意,您可以将EnableScanInQuery集作为查询中的FeedOptions传递给true,或者在时间字段上设置精度为-1的范围索引

你可以像David提到的那样将日期存储为历元,但你不必这样做

以下是您的查询结果:

字符串currentTime=DateTime.UtcNow.ToString(“o”)

var myQuery=Client.CreateDocumentQuery(MyCollection.DocumentsLink, “从c中选择*,其中c.Time>='”+currentTime+“'”,新的FeedOptions{EnableScanInQuery=true})
.AsEnumerable()

你读过这个吗+我要写这封信。它使用ISO-8601字符串,这是我在DocumentDB中存储日期时间数据的建议。感谢您的建议,但我仍然收到相同的错误。或者,您可以使用ISO-8601字符串。我认为默认情况下,DateTime对象是以这种方式序列化的(尽管我认为它们没有正确地反序列化),然后需要在字段上放置一个精度为-1的字符串范围索引。这种方法的好处在于,它们在数据库中是人类可读的。有些人认为它效率较低,但我在实验中没有看到任何性能影响。
{
    "Time": 1408318702
}
public class FooBar
{
     [JsonConverter(typeof(EpochDateTimeConverter))]
     public DateTime Time { get; set; }
}


public class EpochDateTimeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, 
                                  object value, 
                                   JsonSerializer serializer)
    {
        int seconds;
        if (value is DateTime)
        {
            DateTime dt = (DateTime)value;
            if (!dt.Equals(DateTime.MinValue))
                seconds = dt.ToEpoch();
            else
                seconds = int.MinValue;
        }
        else
        {
            throw new Exception("Expected date object value.");
        }

        writer.WriteValue(seconds);
    }

    public override object ReadJson(JsonReader reader, 
                                    Type type, 
                                    object value, 
                                    JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.None || reader.TokenType == JsonToken.Null) 
            return null;

        if (reader.TokenType != JsonToken.Integer)
        {
            throw new Exception(
                 string.Format("Unexpected token parsing date. Expected Integer, got {0}.",
                               reader.TokenType));
        }

        int seconds = (int)reader.Value;
        return new DateTime(1970, 1, 1).AddSeconds(seconds);
    }
}
public static class Extensions
{
    public static int ToEpoch(this DateTime date)
    {
        if (date == null) return int.MinValue;
        DateTime epoch = new DateTime(1970, 1, 1);
        TimeSpan epochTimeSpan = date - epoch;
        return (int)epochTimeSpan.TotalSeconds;
    }
}