Kar*_*dox 3 c# linq datetime azure azure-cosmosdb
我想查询文档上的更新时间戳_ts以获取自一段时间以来未发生变异的文档.
当我在azure门户中创建选择查询时,这可以:
SELECT TOP 10 c.id FROM c WHERE c._ts < 6.35909919217878E+17
Run Code Online (Sandbox Code Playgroud)
奇数是使用datetime对象创建的Ticks,见下文.
但是当我尝试通过LINQ创建它时,它不会这样做,因为你没有_ts而是将Timestamp作为DateTime对象.当我尝试输入一个完整的DateTime对象来与Timestamp进行比较时,它会崩溃,说它不支持它.所以我试试这个:
DocRepo.Get(x => x.Timestamp.Ticks < CloseDate.Ticks);
Run Code Online (Sandbox Code Playgroud)
这导致什么都没有,当我看到执行的查询时,它将此作为选择查询:
SELECT * FROM root WHERE root[\"_ts\"][\"Ticks\"] < 6.35909943137688E+17
Run Code Online (Sandbox Code Playgroud)
是否可以查询_ts时间戳或者我必须有一个额外的updatedAt字段来执行它,这似乎是多余的.
您的查询有几个问题.在您的第一个查询中,您将"Ticks"(一千万分之一秒 - 请参见此处)与_ts值进行比较,该值最有可能返回集合中的所有文档,因为_ts值是以下测量的POSIX(Unix)时间秒见这里.它们也不是基于同一时代.Unix值从1,1,1970午夜开始,其中Ticks从午夜开始1,1,0001因此,_ts值总是比Ticks值小得多(更不用提到1969年了!).您需要将日期转换为Unix时间值.您可以创建一个Extension方法来帮助您执行此操作:
public static long ToUnixTime(this DateTime date)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (long)(date - epoch).TotalSeconds;
}
Run Code Online (Sandbox Code Playgroud)
至于Linq语句,你不能(不幸的是)将DateTime放入Linq查询中,因为DateTime值不会转换为const(这是你得到的错误).因此,在这两种情况下,您都无法轻松地比较_ts值或TimeStamp值.
那么该怎么办?好吧,在查看DocumentDB SDK时,如果查看TimeStamp的定义,您将看到以下内容:
// Summary:
// Gets the last modified timestamp associated with the resource.
[JsonConverter(typeof(UnixDateTimeConverter))]
[JsonProperty(PropertyName = "_ts")]
public virtual DateTime Timestamp { get; internal set; }
Run Code Online (Sandbox Code Playgroud)
因此,默认情况下,SDK将_ts值转换为DateTime并通过TimeStamp字段公开它.根据DocRepo返回的类型,您可以做几件事.如果它是默认的Document类型,您可以创建一个新类并从Docment类型继承,如下所示:
public class MyDocument : Document
{
public long _ts
{
get; set;
}
}
Run Code Online (Sandbox Code Playgroud)
如果它是您自己的自定义类,则只需将_ts字段添加到您的类中.无论哪种方式,如果_ts字段存在,DocumentDB将填充该字段.然后,如果您添加ToUnixTime扩展方法,您可以像这样编写Linq查询:
DocRepo.Get(x => x._ts < CloseDate.ToUnixTime());
Run Code Online (Sandbox Code Playgroud)
它可能不是一个优雅的解决方案,有人(希望)可能会提出一个更好的解决方案,但我已经证实它对我自己的DocumentDB集合有效.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
2689 次 |
| 最近记录: |