我正在使用LINQ to DocumentDB,我目前正在尝试按日期时间字段过滤返回的记录。我的查询如下:
var mycollection = Client.CreateDocumentQuery<Test>(MyCollection.DocumentsLink)
.Where(d => d.Time >= DateTime.Now)
.AsEnumerable();
但是,此查询始终与消息崩溃:
ExceptionMessage=The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.
ExceptionType=System.InvalidOperationException
ExceptionMessage=Constant of type 'System.DateTime' is not supported.
ExceptionType=Microsoft.Azure.Documents.Linq.DocumentQueryException
发生此错误是因为我使用datetime字段进行过滤。如果我要过滤任何字符串字段,那就完美了。如何防止此错误?
答案 0 :(得分:1)
DateTime
不是受支持的时间,您必须将DateTime
转换为int,以便JSON看起来像这样(例如):
{
"Time": 1408318702
}
您需要使用JsonConverter
并将DateTime
属性视为纪元。此代码借用this source here。
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);
}
}
.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;
}
}
答案 1 :(得分:0)
默认情况下,DocumentDB中的DateTime对象被序列化为ISO 8601字符串格式,例如:&#34; 2016-08-08T22:10:50.000000Z&#34;
在这种情况下,您可以使用SQL语法而不是LINQ,因为不支持DateTime对象。
请注意,您可以在查询中将EnableScanInQuery设置为true作为FeedOptions,或者在时间字段上设置精度为-1的范围索引。
您可以将日期存储为大卫提到的时代,但您不必这样做。
以下是您的查询内容:
string currentTime = DateTime.UtcNow.ToString(&#34; o&#34;);
var myQuery = Client.CreateDocumentQuery(MyCollection.DocumentsLink, &#34; SELECT * FROM c WHERE c.Time&gt; =&#39;&#34; + currentTime +&#34;&#39;&#34;,new FeedOptions {EnableScanInQuery = true}) .AsEnumerable();