Incremental fix for YesSQL provider with And/Or specifications

Fixes #1472
This commit is contained in:
Sipke Schoorstra 2021-09-06 16:30:35 +02:00
parent b007dc7574
commit de9ac4b074
4 changed files with 40 additions and 11 deletions

View file

@ -4,18 +4,18 @@ using LinqKit;
namespace Elsa.Persistence.Specifications
{
internal struct AndSpecification<T> : ISpecification<T>
public struct AndSpecification<T> : ISpecification<T>
{
private readonly ISpecification<T> _left;
private readonly ISpecification<T> _right;
public AndSpecification(ISpecification<T> left, ISpecification<T> right)
{
_right = right;
_left = left;
Right = right;
Left = left;
}
public bool IsSatisfiedBy(T entity) => _left.IsSatisfiedBy(entity) && _right.IsSatisfiedBy(entity);
public Expression<Func<T, bool>> ToExpression() => _left.ToExpression().And(_right.ToExpression());
public bool IsSatisfiedBy(T entity) => Left.IsSatisfiedBy(entity) && Right.IsSatisfiedBy(entity);
public Expression<Func<T, bool>> ToExpression() => Left.ToExpression().And(Right.ToExpression());
public ISpecification<T> Left { get; }
public ISpecification<T> Right { get; }
}
}
}

View file

@ -4,7 +4,7 @@ using System.Linq.Expressions;
namespace Elsa.Persistence.Specifications
{
internal struct NotSpecification<T> : ISpecification<T>
public struct NotSpecification<T> : ISpecification<T>
{
private readonly ISpecification<T> _specification;

View file

@ -4,7 +4,7 @@ using LinqKit;
namespace Elsa.Persistence.Specifications
{
internal struct OrSpecification<T> : ISpecification<T>
public struct OrSpecification<T> : ISpecification<T>
{
private readonly ISpecification<T> _left;
private readonly ISpecification<T> _right;

View file

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
@ -40,6 +41,7 @@ namespace Elsa.Persistence.YesSql.Stores
: Query<WorkflowDefinitionIndex>(session, x => x.DefinitionId.IsIn(s.Ids)).WithVersion(s.VersionOptions),
WorkflowDefinitionVersionIdSpecification s => Query<WorkflowDefinitionIndex>(session, x => x.DefinitionVersionId == s.VersionId),
AndSpecification<WorkflowDefinition> s => MapAndSpecification(session, s),
VersionOptionsSpecification s => Query<WorkflowDefinitionIndex>(session).WithVersion(s.VersionOptions),
_ => AutoMapSpecification<WorkflowDefinitionIndex>(session, specification)
};
@ -51,5 +53,32 @@ namespace Elsa.Persistence.YesSql.Stores
var indexedQuery = query.With<WorkflowDefinitionIndex>();
return orderBy.SortDirection == SortDirection.Ascending ? indexedQuery.OrderBy(expression) : indexedQuery.OrderByDescending(expression);
}
/// TODO: This is a workaround. The real fix might be to remove the specification pattern and replace with repository abstractions with finite methods, or automatically dig into And and Or specifications and map each branch into a YesSQL queryable predicate.
private IQuery<WorkflowDefinitionDocument> MapAndSpecification(ISession session, AndSpecification<WorkflowDefinition> and)
{
var left = and.Left;
var right = and.Right;
if(left is ManyWorkflowDefinitionIdsSpecification manyWorkflowDefinitionIdsSpecification && right is TenantSpecification<WorkflowDefinition> tenantSpecification)
{
return CreateQuery(session, manyWorkflowDefinitionIdsSpecification.Ids, manyWorkflowDefinitionIdsSpecification.VersionOptions, tenantSpecification.TenantId);
}
return AutoMapSpecification<WorkflowDefinitionIndex>(session, and);
}
private IQuery<WorkflowDefinitionDocument> CreateQuery(ISession session, IEnumerable<string> definitionIds, VersionOptions? versionOptions = default, string? tenantId = default)
{
var query = Query<WorkflowDefinitionIndex>(session).Where(x => x.DefinitionId.IsIn(definitionIds));
if (versionOptions != null)
query.WithVersion(versionOptions);
if (!string.IsNullOrWhiteSpace(tenantId))
query.Where(x => x.TenantId == tenantId);
return query;
}
}
}