From 6329a3b8050bc67c6a6b8b5ec2b2b77643b1fec7 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 30 Aug 2023 18:23:59 +0200 Subject: [PATCH] Use mapping expression for correct EF core projections (#4376) --- .../DbContextOptionsBuilderExtensions.cs | 7 ++++ .../Management/WorkflowDefinitionStore.cs | 8 ++-- .../Management/WorkflowInstanceStore.cs | 8 ++-- .../Models/WorkflowDefinitionSummary.cs | 41 ++++++++++++++----- .../Models/WorkflowInstanceSummary.cs | 20 +++++++++ 5 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Extensions/DbContextOptionsBuilderExtensions.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Extensions/DbContextOptionsBuilderExtensions.cs index 80bbca987..97c28bcc5 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Extensions/DbContextOptionsBuilderExtensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Extensions/DbContextOptionsBuilderExtensions.cs @@ -2,12 +2,19 @@ using Elsa.EntityFrameworkCore.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.Logging; // ReSharper disable once CheckNamespace namespace Elsa.EntityFrameworkCore.Extensions; +/// +/// Provides extension methods to configure Entity Framework Core with SQLite. +/// public static class DbContextOptionsBuilderExtensions { + /// + /// Configures Entity Framework Core with SQLite. + /// public static DbContextOptionsBuilder UseElsaSqlite(this DbContextOptionsBuilder builder, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default, Action? configure = default) => builder .UseElsaDbContextOptions(options) diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs index 14b1757e6..eef3aeaf7 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowDefinitionStore.cs @@ -77,7 +77,7 @@ public class EFCoreWorkflowDefinitionStore : IWorkflowDefinitionStore var queryable = Filter(set.AsQueryable(), filter); var count = await queryable.LongCountAsync(cancellationToken); queryable = Paginate(queryable, pageArgs); - var results = await queryable.Select(x => WorkflowDefinitionSummary.FromDefinition(x)).ToListAsync(cancellationToken); + var results = await queryable.Select(WorkflowDefinitionSummary.FromDefinitionExpression()).ToListAsync(cancellationToken); return Page.Of(results, count); } @@ -92,7 +92,7 @@ public class EFCoreWorkflowDefinitionStore : IWorkflowDefinitionStore var count = await queryable.LongCountAsync(cancellationToken); queryable = Paginate(queryable, pageArgs); - var results = await queryable.Select(x => WorkflowDefinitionSummary.FromDefinition(x)).ToListAsync(cancellationToken); + var results = await queryable.Select(WorkflowDefinitionSummary.FromDefinitionExpression()).ToListAsync(cancellationToken); return Page.Of(results, count); } @@ -102,7 +102,7 @@ public class EFCoreWorkflowDefinitionStore : IWorkflowDefinitionStore await using var dbContext = await _store.CreateDbContextAsync(cancellationToken); var set = dbContext.WorkflowDefinitions.AsNoTracking(); var queryable = Filter(set.AsQueryable(), filter); - return await queryable.Select(x => WorkflowDefinitionSummary.FromDefinition(x)).ToListAsync(cancellationToken); + return await queryable.Select(WorkflowDefinitionSummary.FromDefinitionExpression()).ToListAsync(cancellationToken); } /// @@ -111,7 +111,7 @@ public class EFCoreWorkflowDefinitionStore : IWorkflowDefinitionStore await using var dbContext = await _store.CreateDbContextAsync(cancellationToken); var set = dbContext.WorkflowDefinitions.AsNoTracking(); var queryable = Filter(set.AsQueryable(), filter).OrderBy(order); - return await queryable.Select(x => WorkflowDefinitionSummary.FromDefinition(x)).ToListAsync(cancellationToken); + return await queryable.Select(WorkflowDefinitionSummary.FromDefinitionExpression()).ToListAsync(cancellationToken); } /// diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs index e4f66ad34..88717865c 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Management/WorkflowInstanceStore.cs @@ -66,7 +66,7 @@ public class EFCoreWorkflowInstanceStore : IWorkflowInstanceStore public async ValueTask> SummarizeManyAsync(WorkflowInstanceFilter filter, PageArgs pageArgs, CancellationToken cancellationToken = default) { var count = await _store.QueryAsync(query => Filter(query, filter), x => x.Id, cancellationToken).LongCount(); - var entities = await _store.QueryAsync(query => Filter(query, filter).Paginate(pageArgs), x => WorkflowInstanceSummary.FromInstance(x), cancellationToken).ToList(); + var entities = await _store.QueryAsync(query => Filter(query, filter).Paginate(pageArgs), WorkflowInstanceSummary.FromInstanceExpression(), cancellationToken).ToList(); return Page.Of(entities, count); } @@ -78,18 +78,18 @@ public class EFCoreWorkflowInstanceStore : IWorkflowInstanceStore var queryable = Filter(set.AsQueryable(), filter).OrderBy(order); var count = await queryable.LongCountAsync(cancellationToken); queryable = queryable.Paginate(pageArgs); - var entities = await queryable.Select(x => WorkflowInstanceSummary.FromInstance(x)).ToListAsync(cancellationToken); + var entities = await queryable.Select(WorkflowInstanceSummary.FromInstanceExpression()).ToListAsync(cancellationToken); return Page.Of(entities, count); } /// public async ValueTask> SummarizeManyAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) => - await _store.QueryAsync(query => Filter(query, filter), x => WorkflowInstanceSummary.FromInstance(x), cancellationToken).ToList().AsEnumerable(); + await _store.QueryAsync(query => Filter(query, filter), WorkflowInstanceSummary.FromInstanceExpression(), cancellationToken).ToList().AsEnumerable(); /// public async ValueTask> SummarizeManyAsync(WorkflowInstanceFilter filter, WorkflowInstanceOrder order, CancellationToken cancellationToken = default) => - await _store.QueryAsync(query => Filter(query, filter).OrderBy(order), x => WorkflowInstanceSummary.FromInstance(x), cancellationToken).ToList().AsEnumerable(); + await _store.QueryAsync(query => Filter(query, filter).OrderBy(order), WorkflowInstanceSummary.FromInstanceExpression(), cancellationToken).ToList().AsEnumerable(); /// public async ValueTask DeleteAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) => diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs index 72710bfd8..6a46eb20a 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs @@ -1,3 +1,4 @@ +using System.Linq.Expressions; using Elsa.Workflows.Management.Entities; using JetBrains.Annotations; @@ -27,56 +28,74 @@ public class WorkflowDefinitionSummary CreatedAt = workflowDefinition.CreatedAt }; + /// + /// Creates a new instance of the class from the specified instance. + /// + public static Expression> FromDefinitionExpression() => workflowDefinition => new WorkflowDefinitionSummary + { + Id = workflowDefinition.Id, + DefinitionId = workflowDefinition.DefinitionId, + Name = workflowDefinition.Name, + Description = workflowDefinition.Description, + Version = workflowDefinition.Version, + ToolVersion = workflowDefinition.ToolVersion, + IsLatest = workflowDefinition.IsLatest, + IsPublished = workflowDefinition.IsPublished, + ProviderName = workflowDefinition.ProviderName, + MaterializerName = workflowDefinition.MaterializerName, + CreatedAt = workflowDefinition.CreatedAt + }; + /// /// The version ID of the workflow definition. /// public string Id { get; set; } = default!; - + /// /// The ID of the workflow definition. /// public string DefinitionId { get; set; } = default!; - + /// /// The name of the workflow definition. /// public string? Name { get; set; } - + /// /// The description of the workflow definition. /// public string? Description { get; set; } - + /// /// The version of the workflow definition. /// public int? Version { get; set; } - + /// /// The version of the tool that created the workflow definition. /// public Version? ToolVersion { get; set; } - + /// /// Whether this is the latest version of the workflow definition. /// public bool IsLatest { get; set; } - + /// /// Whether this workflow definition is published. /// public bool IsPublished { get; set; } - + /// /// The provider name of the workflow definition. /// public string? ProviderName { get; set; } - + /// /// The materializer name of the workflow definition. /// - public string MaterializerName { get; set; } = default!; - + public string MaterializerName { get; set; } = default!; + /// /// The timestamp when the workflow definition was created. /// diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs index 5d03a1814..1368aa457 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs @@ -1,3 +1,4 @@ +using System.Linq.Expressions; using Elsa.Workflows.Core; using Elsa.Workflows.Management.Entities; using JetBrains.Annotations; @@ -30,6 +31,25 @@ public class WorkflowInstanceSummary FinishedAt = workflowInstance.FinishedAt }; } + + /// + /// Returns a summary view of the specified . + /// + public static Expression> FromInstanceExpression() + => workflowInstance => new WorkflowInstanceSummary + { + Id = workflowInstance.Id, + DefinitionId = workflowInstance.DefinitionId, + DefinitionVersionId = workflowInstance.DefinitionVersionId, + Version = workflowInstance.Version, + Status = workflowInstance.Status, + SubStatus = workflowInstance.SubStatus, + CorrelationId = workflowInstance.CorrelationId, + Name = workflowInstance.Name, + CreatedAt = workflowInstance.CreatedAt, + UpdatedAt = workflowInstance.UpdatedAt, + FinishedAt = workflowInstance.FinishedAt + }; /// The ID of the workflow instance. public string Id { get; set; } = default!;