C# 如果DateTime.Now不是';还不够好吗?

C# 如果DateTime.Now不是';还不够好吗?,c#,datetime,cqrs,event-sourcing,C#,Datetime,Cqrs,Event Sourcing,好的,这就是问题所在。我们在事件源中使用CQR,在聚合实例的每个提交序列中使用事件流。每个流都会保留其各自的创建日期,但问题是所有这些都发生得太快了,这意味着某些聚合事件流(属于某些流程的一部分,如注册、通知等)的日期完全相同。因此,当我们必须重播事件时,按创建日期对流进行排序是不起作用的,因为有一些事件流在时间上是相关的,但它们发生得如此之快,以至于看起来它们是并行发生的(这意味着我们使用了DateTime.UtcNow,并且日期等于纳秒) 对于那些不知道什么是CQR或事件来源的人 假设您有一

好的,这就是问题所在。我们在事件源中使用CQR,在聚合实例的每个提交序列中使用事件流。每个流都会保留其各自的创建日期,但问题是所有这些都发生得太快了,这意味着某些聚合事件流(属于某些流程的一部分,如注册、通知等)的日期完全相同。因此,当我们必须重播事件时,按创建日期对流进行排序是不起作用的,因为有一些事件流在时间上是相关的,但它们发生得如此之快,以至于看起来它们是并行发生的(这意味着我们使用了DateTime.UtcNow,并且日期等于纳秒)

对于那些不知道什么是CQR或事件来源的人

假设您有一个资源列表,每个项目都有其创建日期。
关键是要知道列表中项目的创建顺序。请记住,有多个线程在列表中创建和添加项目。问题是,当一个线程必须在列表中创建并添加两个项目时,它们的创建日期与之匹配,因此无法按日期正确排序。顺便说一句,pc在我的pc DateTime上很重要。现在不等于DateTime。现在在服务器上它是。实际上,在一个同事的电脑上,添加25000次DateTime。现在列表的结果是列表的第一个和最后一个元素等于纳秒(精确匹配)

通过调用Windows API,您可以获得一个准确的数字,并将其用作时间戳,该API将以非常高的分辨率在线程之间提供一致的值

当然,这只提供与一台特定计算机相关的值;如果要比较在两台不同的计算机上创建的时间戳,则不能使用它

但是,请注意(来自Windows API文档):

在多处理器计算机上,调用哪个处理器并不重要。但是,由于基本输入/输出系统(BIOS)或硬件抽象层(HAL)中的错误,您可以在不同的处理器上获得不同的结果

(我自己在任何硬件上都没有遇到上述错误。)

您可以通过C#访问性能计数器,如下所示:

public long PerformanceCounter()
{
    long result;
    QueryPerformanceCounter(out result);
    return result;
}

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

时间戳是一段有用的元数据。正如你所发现的,这不是一个可靠的排序标准。想象一下,你在你的机器上想出了一些解决方案,但现在不得不使用两台机器?你能让他们的时钟在一纳秒之内保持同步吗?少一点

在事件源中,典型的保证是仅在单个流中对事件进行排序,例如一个聚合。这是你的交易担保。为什么不使用整数来跟踪流中每个事件的序列?您的聚合可以生成它,因为它一直在跟踪所有事件


如果希望跨流排序,则必须集中生成该序列号(使用表示的耦合),或者接受多个流的多次读取并不总是在同一顺序内返回事件,只需要对一个流中的事件进行排序。

相关:为什么不在创建时间的同时使用增量Id?它很复杂:D我正在尝试做这个atm,但它遇到了困难。如果我们这样做,它将是一个黑客而不是一个实际的解决方案。您需要时间戳在多个系统中保持准确,还是只需要相对于单个系统按时间排序?