From 8eedcd5d8143f5bc05deaec7ea16dca93fcda94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 17:37:48 +0200 Subject: [PATCH 1/8] sup --- .../Create/CreateDialogCommandValidator.cs | 14 +++ .../Commands/Create/CreateDialogDto.cs | 2 +- .../Features/Aggregate/AggregateExtensions.cs | 10 +- .../Dialogs/Commands/CreateDialogTests.cs | 106 +++++++++++++++++- 4 files changed, 127 insertions(+), 5 deletions(-) diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs index 93d5ad0a6..7047eaf77 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs @@ -31,6 +31,20 @@ public CreateDialogCommandValidator( .IsValidUuidV7() .UuidV7TimestampIsInPast(); + RuleFor(x => x.CreatedAt) + .IsInPast(); + + RuleFor(x => x.CreatedAt) + .NotEmpty() + .WithMessage($"{{PropertyName}} must not be empty when '{nameof(CreateDialogCommand.UpdatedAt)} is set.") + .When(x => x.UpdatedAt != default); + + RuleFor(x => x.UpdatedAt) + .IsInPast() + .GreaterThanOrEqualTo(x => x.CreatedAt) + .WithMessage($"{{PropertyName}} must be greater than or equal to '{nameof(CreateDialogCommand.CreatedAt)}'.") + .When(x => x.CreatedAt != default && x.UpdatedAt != default); + RuleFor(x => x.ServiceResource) .NotNull() .IsValidUri() diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs index 037778d46..7468295f5 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs @@ -86,7 +86,7 @@ public class CreateDialogDto /// If not supplied, the current date /time will be used. /// /// 2022-12-31T23:59:59Z - public DateTimeOffset UpdatedAt { get; set; } // TODO: This does not work, as UpdatedAt is always overwritten + public DateTimeOffset UpdatedAt { get; set; } /// /// The aggregated status of the dialog. diff --git a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs index 6b3c38a78..e51507dbf 100644 --- a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs +++ b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs @@ -44,11 +44,19 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac restored.OnRestore(aggregateNode, utcNow); } - if (aggregateNode.Entity is IUpdateableEntity updatable) + if (aggregateNode.Entity is IUpdateableEntity updatable && aggregateNode.State is AggregateNodeState.Modified) { updatable.Update(utcNow); } + if (aggregateNode.Entity is IUpdateableEntity createdUpdatable && aggregateNode.State is AggregateNodeState.Added) + { + if (createdUpdatable.UpdatedAt == default) + { + createdUpdatable.Update(utcNow); + } + } + if (aggregateNode.Entity is IVersionableEntity versionable) { versionable.NewVersion(); diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs index c02a80129..00ef51363 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs @@ -1,7 +1,7 @@ -using Digdir.Domain.Dialogporten.Application.Integration.Tests.Common; +using Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Queries.Get; +using Digdir.Domain.Dialogporten.Application.Integration.Tests.Common; using Digdir.Tool.Dialogporten.GenerateFakeData; using FluentAssertions; -using Medo; using static Digdir.Domain.Dialogporten.Application.Integration.Tests.UuiDv7Utils; namespace Digdir.Domain.Dialogporten.Application.Integration.Tests.Features.V1.ServiceOwner.Dialogs.Commands; @@ -109,5 +109,105 @@ public async Task Create_CreateDialog_WhenDialogIsComplex() success.Value.Should().Be(expectedDialogId); } - // TODO: Add tests + [Fact] + public async Task Can_Create_Dialog_With_UpdatedAt_Supplied() + { + // Arrange + var dialogId = GenerateBigEndianUuidV7(); + var createdAt = DateTimeOffset.UtcNow.AddYears(-20); + var updatedAt = DateTimeOffset.UtcNow.AddYears(-15); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + + // Act + var createDialogResult = await Application.Send(createDialogCommand); + var getDialogQuery = new GetDialogQuery + { + DialogId = dialogId + }; + + var getDialogResponse = await Application.Send(getDialogQuery); + + // Assert + createDialogResult.TryPickT0(out var dialogCreatedSuccess, out _).Should().BeTrue(); + dialogCreatedSuccess.Value.Should().Be(dialogId); + + getDialogQuery.Should().NotBeNull(); + getDialogResponse.TryPickT0(out var dialog, out _).Should().BeTrue(); + dialog.Should().NotBeNull(); + dialog.CreatedAt.Should().Be(createdAt); + dialog.UpdatedAt.Should().Be(updatedAt); + } + + [Fact] + public async Task Cant_Create_Dialog_With_UpdatedAt_Supplied_Without_CreatedAt_Supplied() + { + // Arrange + var dialogId = GenerateBigEndianUuidV7(); + var updatedAt = DateTimeOffset.UtcNow.AddYears(-15); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt); + + // Act + var response = await Application.Send(createDialogCommand); + + // Assert + response.TryPickT2(out var validationError, out _).Should().BeTrue(); + validationError.Should().NotBeNull(); + validationError.Errors.Should().Contain(e => e.ErrorMessage.Contains(nameof(createDialogCommand.UpdatedAt))); + } + + [Fact] + public async Task Cant_Create_Dialog_With_UpdatedAt_Date_Earlier_Than_CreatedAt_Date() + { + // Arrange + var dialogId = GenerateBigEndianUuidV7(); + var createdAt = DateTimeOffset.UtcNow.AddYears(-10); + var updatedAt = DateTimeOffset.UtcNow.AddYears(-15); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + + // Act + var response = await Application.Send(createDialogCommand); + + // Assert + response.TryPickT2(out var validationError, out _).Should().BeTrue(); + validationError.Should().NotBeNull(); + validationError.Errors.Should().Contain(e => e.ErrorMessage.Contains(nameof(createDialogCommand.CreatedAt))); + } + + [Fact] + public async Task Cant_Create_Dialog_With_UpdatedAt_Or_CreatedAt_In_The_Future() + { + // Arrange + var dialogId = GenerateBigEndianUuidV7(); + var now = DateTimeOffset.UtcNow; + var createdAt = now.AddYears(1); + var updatedAt = now.AddYears(1); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + + // Act + var response = await Application.Send(createDialogCommand); + + // + response.TryPickT2(out var validationError, out _).Should().BeTrue(); + validationError.Should().NotBeNull(); + validationError.Errors.Should().Contain(e => e.ErrorMessage.Contains("in the past")); + } + + [Fact] + public async Task Can_Create_Dialog_With_UpdatedAt_And_CreatedAt_Being_Equal() + { + // Arrange + var dialogId = GenerateBigEndianUuidV7(); + var now = DateTimeOffset.UtcNow; + var createdAt = now.AddYears(-1); + var updatedAt = now.AddYears(-1); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + + // Act + var response = await Application.Send(createDialogCommand); + + // Assert + response.TryPickT0(out var success, out _).Should().BeTrue(); + success.Should().NotBeNull(); + success.Value.Should().Be(dialogId); + } } From 72c4ae6ac2de166a49679fdebf7bac1560656b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 17:51:20 +0200 Subject: [PATCH 2/8] remove stuff --- .../Dialogs/Commands/CreateDialogTests.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs index 00ef51363..d2e83a05a 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs @@ -142,9 +142,8 @@ public async Task Can_Create_Dialog_With_UpdatedAt_Supplied() public async Task Cant_Create_Dialog_With_UpdatedAt_Supplied_Without_CreatedAt_Supplied() { // Arrange - var dialogId = GenerateBigEndianUuidV7(); var updatedAt = DateTimeOffset.UtcNow.AddYears(-15); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt); // Act var response = await Application.Send(createDialogCommand); @@ -159,10 +158,9 @@ public async Task Cant_Create_Dialog_With_UpdatedAt_Supplied_Without_CreatedAt_S public async Task Cant_Create_Dialog_With_UpdatedAt_Date_Earlier_Than_CreatedAt_Date() { // Arrange - var dialogId = GenerateBigEndianUuidV7(); var createdAt = DateTimeOffset.UtcNow.AddYears(-10); var updatedAt = DateTimeOffset.UtcNow.AddYears(-15); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt, createdAt: createdAt); // Act var response = await Application.Send(createDialogCommand); @@ -177,11 +175,10 @@ public async Task Cant_Create_Dialog_With_UpdatedAt_Date_Earlier_Than_CreatedAt_ public async Task Cant_Create_Dialog_With_UpdatedAt_Or_CreatedAt_In_The_Future() { // Arrange - var dialogId = GenerateBigEndianUuidV7(); var now = DateTimeOffset.UtcNow; var createdAt = now.AddYears(1); var updatedAt = now.AddYears(1); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt, createdAt: createdAt); // Act var response = await Application.Send(createDialogCommand); @@ -196,11 +193,10 @@ public async Task Cant_Create_Dialog_With_UpdatedAt_Or_CreatedAt_In_The_Future() public async Task Can_Create_Dialog_With_UpdatedAt_And_CreatedAt_Being_Equal() { // Arrange - var dialogId = GenerateBigEndianUuidV7(); var now = DateTimeOffset.UtcNow; var createdAt = now.AddYears(-1); var updatedAt = now.AddYears(-1); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(id: dialogId, updatedAt: updatedAt, createdAt: createdAt); + var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt, createdAt: createdAt); // Act var response = await Application.Send(createDialogCommand); @@ -208,6 +204,5 @@ public async Task Can_Create_Dialog_With_UpdatedAt_And_CreatedAt_Being_Equal() // Assert response.TryPickT0(out var success, out _).Should().BeTrue(); success.Should().NotBeNull(); - success.Value.Should().Be(dialogId); } } From eeeef41680462de4c75a4afc8db20a68b914b82e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 18:51:14 +0200 Subject: [PATCH 3/8] be close to --- .../V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs index d2e83a05a..faad61045 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs @@ -134,8 +134,8 @@ public async Task Can_Create_Dialog_With_UpdatedAt_Supplied() getDialogQuery.Should().NotBeNull(); getDialogResponse.TryPickT0(out var dialog, out _).Should().BeTrue(); dialog.Should().NotBeNull(); - dialog.CreatedAt.Should().Be(createdAt); - dialog.UpdatedAt.Should().Be(updatedAt); + dialog.CreatedAt.Should().BeCloseTo(createdAt, precision: TimeSpan.FromMicroseconds(10)); + dialog.UpdatedAt.Should().BeCloseTo(updatedAt, precision: TimeSpan.FromMicroseconds(10)); } [Fact] From 9899e57556ef51d7610815c5554ad6af86e8c41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 19:36:02 +0200 Subject: [PATCH 4/8] add missing '' --- .../Dialogs/Commands/Create/CreateDialogCommandValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs index 7047eaf77..e1704d187 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs @@ -42,7 +42,7 @@ public CreateDialogCommandValidator( RuleFor(x => x.UpdatedAt) .IsInPast() .GreaterThanOrEqualTo(x => x.CreatedAt) - .WithMessage($"{{PropertyName}} must be greater than or equal to '{nameof(CreateDialogCommand.CreatedAt)}'.") + .WithMessage($"'{{PropertyName}}' must be greater than or equal to '{nameof(CreateDialogCommand.CreatedAt)}'.") .When(x => x.CreatedAt != default && x.UpdatedAt != default); RuleFor(x => x.ServiceResource) From 78fe683cac11781824a84a72ca39295166f3c5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 21:31:45 +0200 Subject: [PATCH 5/8] ... --- .../Dialogs/Commands/CreateDialogTests.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs index faad61045..db17226ed 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/CreateDialogTests.cs @@ -175,10 +175,9 @@ public async Task Cant_Create_Dialog_With_UpdatedAt_Date_Earlier_Than_CreatedAt_ public async Task Cant_Create_Dialog_With_UpdatedAt_Or_CreatedAt_In_The_Future() { // Arrange - var now = DateTimeOffset.UtcNow; - var createdAt = now.AddYears(1); - var updatedAt = now.AddYears(1); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt, createdAt: createdAt); + var aYearFromNow = DateTimeOffset.UtcNow.AddYears(1); + var createDialogCommand = DialogGenerator + .GenerateFakeDialog(updatedAt: aYearFromNow, createdAt: aYearFromNow); // Act var response = await Application.Send(createDialogCommand); @@ -193,10 +192,9 @@ public async Task Cant_Create_Dialog_With_UpdatedAt_Or_CreatedAt_In_The_Future() public async Task Can_Create_Dialog_With_UpdatedAt_And_CreatedAt_Being_Equal() { // Arrange - var now = DateTimeOffset.UtcNow; - var createdAt = now.AddYears(-1); - var updatedAt = now.AddYears(-1); - var createDialogCommand = DialogGenerator.GenerateFakeDialog(updatedAt: updatedAt, createdAt: createdAt); + var aYearAgo = DateTimeOffset.UtcNow.AddYears(-1); + var createDialogCommand = DialogGenerator + .GenerateFakeDialog(updatedAt: aYearAgo, createdAt: aYearAgo); // Act var response = await Application.Send(createDialogCommand); From d10f1c1ed273dc9a8508042cb27c64e6c07435f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Tue, 10 Sep 2024 12:40:31 +0200 Subject: [PATCH 6/8] --wip-- [skip ci] --- .../Features/Aggregate/AggregateExtensions.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs index e51507dbf..0b904d960 100644 --- a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs +++ b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs @@ -34,6 +34,31 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac updated.OnUpdate(aggregateNode, utcNow); } + + + + + + + + + + + + + + + + + + + + + + + + + if (aggregateNode.Entity is IAggregateDeletedHandler deleted && aggregateNode.State is AggregateNodeState.Deleted) { deleted.OnDelete(aggregateNode, utcNow); From 9fe2c389a444e7fa1608923fdedce8aa6e28a5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Wed, 11 Sep 2024 11:35:30 +0200 Subject: [PATCH 7/8] sup --- .../Features/Aggregate/AggregateNode.cs | 20 +++++++++ .../Features/Aggregate/AggregateExtensions.cs | 45 ++++--------------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs b/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs index 9c729f4f2..74b567f56 100644 --- a/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs +++ b/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs @@ -88,6 +88,26 @@ internal static AggregateNode Create(Type type, object entity, AggregateNodeStat /// Convenience method to check if the state of the node is and not by a child node. /// public bool IsDirectlyModified() => State is AggregateNodeState.Modified && !ModifiedByChild; + + /// + /// Convenience method to check if the state of the node is . + /// + public bool IsAdded() => State is AggregateNodeState.Added; + + /// + /// Convenience method to check if the state of the node is . + /// + public bool IsModified() => State is AggregateNodeState.Modified; + + /// + /// Convenience method to check if the state of the node is . + /// + public bool IsRestored() => State is AggregateNodeState.Restored; + + /// + /// Convenience method to check if the state of the node is . + /// + public bool IsDeleted() => State is AggregateNodeState.Deleted; } /// diff --git a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs index 0b904d960..39cb38ebf 100644 --- a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs +++ b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs @@ -24,61 +24,31 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac foreach (var (_, aggregateNode) in aggregateNodeByEntry) { - if (aggregateNode.Entity is IAggregateCreatedHandler created && aggregateNode.State is AggregateNodeState.Added) + if (aggregateNode.Entity is IAggregateCreatedHandler created && aggregateNode.IsAdded()) { created.OnCreate(aggregateNode, utcNow); } - if (aggregateNode.Entity is IAggregateUpdatedHandler updated && aggregateNode.State is AggregateNodeState.Modified) + if (aggregateNode.Entity is IAggregateUpdatedHandler updated && aggregateNode.IsModified()) { updated.OnUpdate(aggregateNode, utcNow); } - - - - - - - - - - - - - - - - - - - - - - - - - - if (aggregateNode.Entity is IAggregateDeletedHandler deleted && aggregateNode.State is AggregateNodeState.Deleted) + if (aggregateNode.Entity is IAggregateDeletedHandler deleted && aggregateNode.IsDeleted()) { deleted.OnDelete(aggregateNode, utcNow); } - if (aggregateNode.Entity is IAggregateRestoredHandler restored && aggregateNode.State is AggregateNodeState.Restored) + if (aggregateNode.Entity is IAggregateRestoredHandler restored && aggregateNode.IsRestored()) { restored.OnRestore(aggregateNode, utcNow); } - if (aggregateNode.Entity is IUpdateableEntity updatable && aggregateNode.State is AggregateNodeState.Modified) + if (aggregateNode.Entity is IUpdateableEntity updatable) { - updatable.Update(utcNow); - } - - if (aggregateNode.Entity is IUpdateableEntity createdUpdatable && aggregateNode.State is AggregateNodeState.Added) - { - if (createdUpdatable.UpdatedAt == default) + if (aggregateNode.IsModified() || (aggregateNode.IsAdded() && updatable.UpdatedAt == default)) { - createdUpdatable.Update(utcNow); + updatable.Update(utcNow); } } @@ -89,6 +59,7 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac } } + internal static ModelBuilder AddAggregateEntities(this ModelBuilder modelBuilder) { // This will eager load entire aggregate trees for ALL queries unless explicitly From 89ef4caaee81bed1ad552990b819117d30268050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Wed, 11 Sep 2024 12:53:12 +0200 Subject: [PATCH 8/8] halp --- .../Features/Aggregate/AggregateNode.cs | 9 +++++++++ .../Features/Aggregate/AggregateExtensions.cs | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs b/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs index 74b567f56..297dca3fc 100644 --- a/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs +++ b/src/Digdir.Library.Entity.Abstractions/Features/Aggregate/AggregateNode.cs @@ -1,4 +1,5 @@ using System.Reflection; +using Digdir.Library.Entity.Abstractions.Features.Updatable; namespace Digdir.Library.Entity.Abstractions.Features.Aggregate; @@ -108,6 +109,14 @@ internal static AggregateNode Create(Type type, object entity, AggregateNodeStat /// Convenience method to check if the state of the node is . /// public bool IsDeleted() => State is AggregateNodeState.Deleted; + + /// + /// Convenience method to check if the state of the node is , + /// and that UpdatedAt is the default value. + /// + /// + public bool IsAddedWithDefaultUpdatedAt(IUpdateableEntity updatable) + => IsAdded() && updatable.UpdatedAt == default; } /// diff --git a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs index 39cb38ebf..3a6085906 100644 --- a/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs +++ b/src/Digdir.Library.Entity.EntityFrameworkCore/Features/Aggregate/AggregateExtensions.cs @@ -46,7 +46,7 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac if (aggregateNode.Entity is IUpdateableEntity updatable) { - if (aggregateNode.IsModified() || (aggregateNode.IsAdded() && updatable.UpdatedAt == default)) + if (aggregateNode.IsModified() || aggregateNode.IsAddedWithDefaultUpdatedAt(updatable)) { updatable.Update(utcNow); } @@ -59,7 +59,6 @@ internal static async Task HandleAggregateEntities(this ChangeTracker changeTrac } } - internal static ModelBuilder AddAggregateEntities(this ModelBuilder modelBuilder) { // This will eager load entire aggregate trees for ALL queries unless explicitly