Use mapping expression for correct EF core projections (#4376)

This commit is contained in:
Sipke Schoorstra 2023-08-30 18:23:59 +02:00 committed by GitHub
parent 45d194125d
commit 6329a3b805
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 19 deletions

View file

@ -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;
/// <summary>
/// Provides extension methods to configure Entity Framework Core with SQLite.
/// </summary>
public static class DbContextOptionsBuilderExtensions
{
/// <summary>
/// Configures Entity Framework Core with SQLite.
/// </summary>
public static DbContextOptionsBuilder UseElsaSqlite(this DbContextOptionsBuilder builder, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default, Action<SqliteDbContextOptionsBuilder>? configure = default) =>
builder
.UseElsaDbContextOptions(options)

View file

@ -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);
}
/// <inheritdoc />
@ -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);
}
/// <inheritdoc />

View file

@ -66,7 +66,7 @@ public class EFCoreWorkflowInstanceStore : IWorkflowInstanceStore
public async ValueTask<Page<WorkflowInstanceSummary>> 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<WorkflowInstanceSummary>(query => Filter(query, filter).Paginate(pageArgs), x => WorkflowInstanceSummary.FromInstance(x), cancellationToken).ToList();
var entities = await _store.QueryAsync<WorkflowInstanceSummary>(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);
}
/// <inheritdoc />
public async ValueTask<IEnumerable<WorkflowInstanceSummary>> 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();
/// <inheritdoc />
public async ValueTask<IEnumerable<WorkflowInstanceSummary>> SummarizeManyAsync<TOrderBy>(WorkflowInstanceFilter filter, WorkflowInstanceOrder<TOrderBy> 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();
/// <inheritdoc />
public async ValueTask<long> DeleteAsync(WorkflowInstanceFilter filter, CancellationToken cancellationToken = default) =>

View file

@ -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
};
/// <summary>
/// Creates a new instance of the <see cref="WorkflowDefinitionSummary"/> class from the specified <see cref="WorkflowDefinition"/> instance.
/// </summary>
public static Expression<Func<WorkflowDefinition, WorkflowDefinitionSummary>> 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
};
/// <summary>
/// The version ID of the workflow definition.
/// </summary>
public string Id { get; set; } = default!;
/// <summary>
/// The ID of the workflow definition.
/// </summary>
public string DefinitionId { get; set; } = default!;
/// <summary>
/// The name of the workflow definition.
/// </summary>
public string? Name { get; set; }
/// <summary>
/// The description of the workflow definition.
/// </summary>
public string? Description { get; set; }
/// <summary>
/// The version of the workflow definition.
/// </summary>
public int? Version { get; set; }
/// <summary>
/// The version of the tool that created the workflow definition.
/// </summary>
public Version? ToolVersion { get; set; }
/// <summary>
/// Whether this is the latest version of the workflow definition.
/// </summary>
public bool IsLatest { get; set; }
/// <summary>
/// Whether this workflow definition is published.
/// </summary>
public bool IsPublished { get; set; }
/// <summary>
/// The provider name of the workflow definition.
/// </summary>
public string? ProviderName { get; set; }
/// <summary>
/// The materializer name of the workflow definition.
/// </summary>
public string MaterializerName { get; set; } = default!;
public string MaterializerName { get; set; } = default!;
/// <summary>
/// The timestamp when the workflow definition was created.
/// </summary>

View file

@ -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
};
}
/// <summary>
/// Returns a summary view of the specified <see cref="WorkflowInstance"/>.
/// </summary>
public static Expression<Func<WorkflowInstance, WorkflowInstanceSummary>> 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
};
/// <summary>The ID of the workflow instance.</summary>
public string Id { get; set; } = default!;