C# FindModify在哪里适合CQR?
在我当前的应用程序中,我对MongoDB服务器进行了以下MongoDBC# 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
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