C# FindModify在哪里适合CQR?

C# FindModify在哪里适合CQR?,c#,mongodb,cqrs,C#,Mongodb,Cqrs,在我当前的应用程序中,我对MongoDB服务器进行了以下MongoDBFindAndModify调用 public static TEntity PeekForRemoveSync<TEntity>(this MongoCollection<TEntity> collection, string reason) where TEntity : class, IEntity, IUpdatesTrackable, ISyncable, IDeletable, IAp

在我当前的应用程序中,我对MongoDB服务器进行了以下MongoDB
FindAndModify
调用

public static TEntity PeekForRemoveSync<TEntity>(this MongoCollection<TEntity> collection, string reason)
    where TEntity : class, IEntity, IUpdatesTrackable, ISyncable, IDeletable, IApprovable
{
    if (reason == null)
    {
        throw new ArgumentNullException(nameof(reason));
    }

    IMongoQuery query = Query.And(
        Query<TEntity>.EQ(e => e.SyncInfo.IsDirty, true),
        Query<TEntity>.NE(e => e.Deletion, null),
        Query<TEntity>.NE(e => e.Approval, null),
        Query<TEntity>.EQ(e => e.SyncInfo.HumanInvestigateFlag, null),
        Query.Or(
            Query<TEntity>.EQ(e => e.SyncInfo.IsUpdateInProgress, false),
            Query<TEntity>.LT(e => e.SyncInfo.UpdateStartInfo.OccuredOn, DateTime.UtcNow.AddSeconds(-SyncConstants.PeekExpireTimeInSeconds))
        ),
        Query<TEntity>.LTE(e => e.SyncInfo.PeekedCount, MaxPeekedCount)
    );

    return PeekForSync(collection, query, reason);
}

private static TEntity PeekForSync<TEntity>(this MongoCollection<TEntity> collection, IMongoQuery query, string reason)
    where TEntity : class, IEntity, IUpdatesTrackable, ISyncable, IDeletable
{
    UpdateBuilder<TEntity> update = Update<TEntity>
        .Inc(e => e.SyncInfo.PeekedCount, 1)
        .Set(e => e.SyncInfo.UpdateStartInfo, new OccuranceWithReason(reason))
        .Set(e => e.SyncInfo.IsUpdateInProgress, true);

    SortByBuilder<TEntity> sort = SortBy<TEntity>.Descending(e => e.LastUpdatedOn);

    FindAndModifyArgs fmArgs = new FindAndModifyArgs
    {
        Query = query,
        Update = update,
        SortBy = sort,
        VersionReturned = FindAndModifyDocumentVersion.Modified
    };

    FindAndModifyResult result = collection.FindAndModify(fmArgs);

    return result.ModifiedDocument != null
        ? result.GetModifiedDocumentAs<TEntity>()
        : null;
}
publicstatictenty-PeekForRemoveSync(此MongoCollection集合,字符串原因)
其中tenty:class、ienty、IUpdatesTrackable、ISyncable、IDeletable、IApprovable
{
如果(原因==null)
{
抛出新ArgumentNullException(nameof(reason));
}
IMongoQuery=query.And(
EQ(e=>e.SyncInfo.IsDirty,true),
NE(e=>e.删除,空),
Query.NE(e=>e.Approval,null),
EQ(e=>e.SyncInfo.HumanInvestigateFlag,null),
查询。或(
EQ(e=>e.SyncInfo.IsUpdateInProgress,false),
LT(e=>e.SyncInfo.UpdateStartInfo.occurrendon,DateTime.UtcNow.AddSeconds(-SyncConstants.PeekExpireTimeInSeconds))
),
LTE(e=>e.SyncInfo.PeekedCount,maxpekedcount)
);
返回PeekForSync(收集、查询、原因);
}
private static tenty PeekForSync(此MongoCollection集合、IMongoQuery查询、字符串原因)
其中tenty:class、ienty、IUpdatesTrackable、ISyncable、IDeletable
{
UpdateBuilder update=update
.Inc(e=>e.SyncInfo.PeekedCount,1)
.Set(e=>e.SyncInfo.UpdateStartInfo,新发生的原因(reason))
.Set(e=>e.SyncInfo.IsUpdateInProgress,true);
SortByBuilder sort=SortBy.Descending(e=>e.LastUpdateOn);
FindAndModifyArgs fmArgs=新FindAndModifyArgs
{
Query=Query,
更新=更新,
SortBy=sort,
VersionReturned=FindAndModifyDocumentVersion.Modified
};
FindAndModifyResult=collection.FindAndModify(fmArgs);
返回result.ModifiedDocument!=null
?result.GetModifiedDocumentAs()
:null;
}
我是否正在用MongoDB重新设计另一个队列系统?这不是我的本意,而是我的本意。忽略这里的业务逻辑

在CQRS中,查询和命令的含义如下(我相信):

命令:更改系统状态,不返回任何值

查询:不会更改系统的状态并返回一些值


如果是这样的话,我上面的
查找和修改
调用(或类似于此查询的任何其他调用)适合哪里?

我不确定我是否正确回答了你的问题,因此以下是我理解的答案:

我喜欢将其视为并发模式和数据模型指南的组合

数据模型指南是更明显的,毕竟,您现在使用的是多个模型。在非CQRS场景中,对于(未完成的)订单或购物车,可能有以下对象:

{  items : [ { 'sku' : '235423', 'qty' : 3, 'price' : 4.34, ... }, ... ],
   orderStatus : 'in_cart',
   customerId : null,
   ...
}
现在,更新模型本身就很容易,但CQRS告诉您不要这样做。假设我想将产品“1234”添加到该购物车。我可以寄回整个新购物车,当然。但这既低效(我只需要“我想将1个产品1234添加到购物车X”中”的信息),又令人恼火,因为服务器无论如何都必须忽略例如的总价

然而,在其核心,I-CQRS主要是一个并发方案——至少与。通过记录谁在何时更改了什么,我们可以集中负责应用更改、处理冲突、允许撤消/重做和保留审核日志的代码,所有这些都是同时进行的。当然,这是以最终的一致性为代价的,但概念是(至少我是这样解释的)

另外,再看一次购物车,更新模型可能毕竟不是一件小事,因为购物车可能代表了对购物车中对象的锁定(至少对于冲突可能性很高的网站,例如闪购——如果产品在购物车中,我想知道我真的可以购买,比如10分钟)。如果没有命令对象,则必须分析文档是如何从状态1转换到状态2的,以及发生了什么变化,从而不释放任何现有锁,但可能会获取一个新锁(或者释放一个并获取一个新锁)

相反,您可以发送一个
AddToCartCommand

{ item : { 'sku' : '4242342', 'qty' : 4 },
  cartId : 53543 }
如果该产品销售得太快,那也没什么坏处,因为我们没有放弃购物篮-addtocart命令失败,但购物车的状态保持完全不变。如果站点处于高负载状态,并且买方添加了另一个产品,那么该命令可能会成功。对于传统的请求/响应模式,如果可能的话,这并不容易

这可能不是最好的示例,但是假设购物车由多个用户同时填充,那么简单的“last write wins”并发(无锁)或乐观的外观(错误:在这两者之间有人更改了文档)将是有问题的

在CQR中,由于我们不进行即时更新,我们可以避开RPC(告诉我立即发生了什么的“方法调用”)和过度特定于客户端的接口。此外,与RPC与REST不同,CQR至少更深一层。虽然它肯定会对客户机代码产生很大影响,但它对服务器处理信息的方式有着巨大的影响,这种方式是异步的,可能是分布式的,甚至可能涉及完全不同的数据存储(因为模型无论如何都是不同的)

在任何情况下,我认为您发布的代码可能是两个模型通信的地方,即必须应用更改的地方,这可能很棘手。首先,这需要(分布式)事务,因此需要进行大量锁定,并且锁定需要原子更新,因此在这种情况下,
findAndModify
似乎是必要的

我不确定偷看到底是做什么的,但对我来说,你的代码似乎试图在文档上获得一个短锁(来自
IsDirty:true
IsUpdateInProgress:false
标准)

一句话,我会说C