从理论上讲,如果我们在聚合根级别实现乐观并发(更改 AR 中的实体会更改 AR 上的版本),并且假设我们使用时间戳作为版本属性(只是为了简单起见) - 时间线应该是 AR 上的属性还是应该是一侧和另一侧的读取模型的一部分(例如更新)是应用程序服务的单独参数,例如:
[伪]
public class AppService{
.
.
.
public void UpdateSomething(UpdateModelDTO model, int timestamp)
{
repository.GetModel(model.Identifier);
model.UpdateSomething(model.something);
repository.ConcurrencySafeModelUpdate(model, timestamp);
}
}
Run Code Online (Sandbox Code Playgroud)
我看到两者的优点/缺点,但想知道哪个是按书本解决方案?
[更新]
为了回答@guillaume31的问题,我预计通常的情况是:
我不知道它是否重要,但我想将创建/更新版本标识符本身的责任留给我的数据库系统。
我有Product.
Product有一些GeneralDetails,让我们说:sku, name, description。同时,会计师可以Product在某些ProductCalculations部分放置不同的值,例如purchasePrice, stockLevelExpenses, wholeSalesPrice, retailPrice.
所以,到目前为止,Product看起来像:
class Product{
GeneralDetails Details;
ProductCalculations Calculations;
ChangeDetails(GeneralDetails details){}
Recalculate(ProductCalculations calculations{}
}
Run Code Online (Sandbox Code Playgroud)
此设置将生成Product聚合根。但是现在,我想以一种方式拆分它,即产品经理可以输入/更新产品详细信息,但随后该会计师可以介入并独立地更改给定产品的计算,而不会出现并发问题。这将建议将其拆分为 2 个单独的聚合根。
但是,删除ProductDetails聚合也必须意味着删除ProductCalculations,它应该以事务性的方式发生。
假设它们是 2 个聚合根,这意味着它们有 2 个具有相应Delete方法的独立存储库,如何将其实现为原子事务?
我唯一能想到的是在ProductDetails被删除时引发事件,有一个处理程序(DomainService),它使用一些特殊的存储库来处理多个聚合根上的事务。
这种方法有什么问题和/或有更好的方法来处理它吗?
附注。ProductDetails删除时我不能允许最终一致性。
PS2。根据来自@乔恩的意见,Details以及Calculations创建和删除应在当的方式同步Details在创建/删除,Calculations也应创建/删除。另一方面,它们的更新应该是完全独立的。
[从这个问题和评论中跟进:实体是否应该有方法,如果有,如何防止它们被外部聚合调用]
正如标题所说:我不清楚作为孩子的实体的实际/确切目的是什么?
根据我在很多地方读到的内容,这些是作为聚合子项的实体的属性:
在我看来,这转化为几个问题:
那么,为什么我们有一个实体而不是只有值对象?只有值对象、聚合和公开值对象的所有方法(我们已经复制实体信息)看起来更方便。
附注。我想将子实体集中在聚合上,而不是实体集合上。
[更新以回应康斯坦丁·加尔贝努的回答和评论]
那么,实际上,你会有这样的事情吗?
public class Aggregate {
...
private _someNestedEntity;
public SomeNestedEntityImmutableState EntityState {
get {
return this._someNestedEntity.getState();
}
}
public ChangeSomethingOnNestedEntity(params) {
this._someNestedEntity.someCommandMethod(params);
}
}
Run Code Online (Sandbox Code Playgroud) 运行时dotnet test,是否可以显示在控制台中运行的所有测试的列表,而不是某些输出文件?
在控制台中看到这样的列表将是理想的:
x test1
test2
test3
x test4
Run Code Online (Sandbox Code Playgroud)
而不只是整体测试统计信息(运行,失败,跳过)。
我们使用 gzip 压缩,例如:
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
});
Run Code Online (Sandbox Code Playgroud)
由于我们希望避免对小响应进行压缩,因此问题是我们是否可以以某种方式配置 gzip 压缩,使其不用于小于 XY 的响应大小?
直截了当的问题是:Microsoft.Extensions.Options.IOptions是否只能在伞形应用程序(在本例中为Web应用程序)或类库中使用?
例:
在一个n层的asp.net核心应用程序中,我们的服务层依赖于来自appsettings.json文件的一些设置.
我们刚开始的是Startup.cs中的这些内容:
services.Configure<Services.Options.XOptions>(options =>
{
options.OptionProperty1 = Configuration["OptionXSection:OptionXProperty"];
});
Run Code Online (Sandbox Code Playgroud)
然后在服务构造函数中:
ServiceConstructor(IOptions<XOptions> xOptions){}
Run Code Online (Sandbox Code Playgroud)
但这假设在我们的服务层中我们依赖Microsoft.Extensions.Options.
我们不确定这是推荐的还是有更好的做法?
我们的服务类库应该知道DI容器实现,这感觉有点尴尬.
据我所知,该团队的官方建议是将所有数据类型放入单个集合中,这些集合type=someType在文档上具有类似字段以区分类型。
现在,如果我们假设具有分区的大型数据库,其中不同的对象类型可以是:
如何组织事物,以便应该在一起的事物最终在同一个分区中?
例如,假设我们有:
用户
博客帖子
博文评论
如果我们将它们作为单独的类型存储type=user|blogPost|blogPostComment在同一个集合中,我们如何确保用户、他的博客文章和所有相应的评论最终在同一个分区中?是否有一些最佳实践?
[更新] 你能完全避免跨分区查询吗?这应该是一个目标吗?或者你只是想尽量减少它们?例如,您可以为 99% 的案例/查询完美地分区数据,但随后您需要一些仪表板来显示所有数据的聚合。这是你认为不可避免的事情并试图最小化还是有可能完全避免它?
我们在 Azure 应用服务计划中遇到了 CPU 峰值,原因不明。这不是停止服务的东西,但我们想了解这种事情何时以及如何发生。
例如,CPU 百分比在几天内处于 0-1% 的范围内,但突然间它飙升至 98%、45%、60%,然后很快又回到 0-1% 的范围。内存保持在舒适的 40-45% 水平不变,没有传入请求,没有 Web 作业,日志中没有异常,没有失败,服务健康状况良好,没有任何我们可以指出的原因。我们试图通过 kudu > 支持 > 分析(指标)找出...但我们无法提交请求。它只是不断给出错误,稍后再试。
在该应用服务计划中只有一个 Web 应用在运行,它是一个 asp.net core 2.0。网络 API。
有人可以对这种行为有所了解吗?这是正常的吗?如果是这样,为什么会发生?是否存在飙升至 90% 且不会立即恢复的危险?
只是,这是怎么回事?
我们有一个工作流程,其中只有一名团队成员在多个功能分支上工作。工作是这样的,下一个分支都依赖于他之前所做的分支。默认分支是develop.
我们来说说这个场景:
featureA分支,完成工作,推送分支,并在 GitHub 上创建 PRfeatureB分支(基于featureA一个分支),进行工作并进行公关featureC分支,(基于featureB)做工作并公关它featureD分支,(基于featureC)做工作并公关它尚未合并任何 PR。
现在,项目经理介入并开始合并。合并走这样的路:
featureA开发他这边的开发人员这样做:
git checkout develop
git fetch origin
git rebase origin/develop
git checkout featureB
git rebase origin/develop
git push origin featureB
Run Code Online (Sandbox Code Playgroud)此时我们得到错误:
machine /c/Work/ (featureB)
$ git push origin featureB
To https://github.com/x.git
! [rejected] featureB -> featureB (non-fast-forward)
error: failed to push some refs to 'https://github.com/x.git'
hint: Updates …Run Code Online (Sandbox Code Playgroud) 因此,如果集合体中存在实体,那么什么是阻止外部世界执行类似操作的最佳/通常方法Aggregate.Entity.SomeMethod()?(如果实体上存在吸气剂)
应该汇总暴露实体,还是应该让其获取器始终给出实体的值对象表示形式?(实际上是打破直接参考的副本)
或者,另一方面,实体应该是贫血的,其所有方法都移到集合中吗?
我已将asp.net core 2.0.应用程序部署到azure linux docker容器中,并且我试图找出处理应用程序日志的最佳方法。
我只是无法进入一些好的/最佳实践工作流。
当然,对日志有Kudu服务或FTP访问,它们都显示docker日志,但问题是如何很好地处理日志级别?
像往常一样,我想Warning在生产中打开和打开,但如果出现问题,我想打开Trace以查看所有内容,但不进行重新部署/重新启动/任何操作。由于我们在docker中并且无法访问,appsettings.json因此reloadOnChange显然无法正常工作,我不确定该怎么做?
这种情况下的最佳实践是什么?
当我们有事件中心(或任何消息服务)的多个使用者时,如何确保没有消息被处理两次,特别是在使用者自动扩展到多个实例的情况下?
我知道我们可以跟踪最后处理的消息,但话又说回来,在检查消息是否已处理和实际处理之间,其他实例已经可以处理它(竞争条件?。
那么,如何以可扩展的方式解决这个问题呢?
[更新] 我知道建议至少拥有与消费者一样多的分区,但是如果单个消费者无法处理定向到它的消息但需要扩展到多个实例,该怎么办?
我试图了解有关域驱动设计的详细信息,而我遇到了这个问题。我发现了很多例子:
另一方面,有一些示例完全违背它,并从服务中处理所有与存储库相关的工作。
我找不到权威的答案和解释:这被认为是不好的做法吗?如果是,为什么?
azure ×3
asp.net-core ×2
.net-core ×1
concurrency ×1
dotnet-cli ×1
git ×1
git-rebase ×1
github ×1
xunit.net ×1