Fix Dapper persistence provider (#4381)
This commit is contained in:
parent
9d4add767b
commit
fe02011c8b
|
|
@ -9,6 +9,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\modules\Elsa.Dapper.Migrations\Elsa.Dapper.Migrations.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Dapper\Elsa.Dapper.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.EntityFrameworkCore.SqlServer\Elsa.EntityFrameworkCore.SqlServer.csproj" />
|
||||
<ProjectReference Include="..\Elsa\Elsa.csproj" />
|
||||
<ProjectReference Include="..\..\modules\Elsa.Elasticsearch\Elsa.Elasticsearch.csproj" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using Elsa.Dapper.Extensions;
|
||||
using Elsa.Dapper.Services;
|
||||
using Elsa.EntityFrameworkCore.Extensions;
|
||||
using Elsa.EntityFrameworkCore.Modules.Identity;
|
||||
using Elsa.EntityFrameworkCore.Modules.Management;
|
||||
|
|
@ -11,13 +12,13 @@ using Elsa.MongoDb.Modules.Identity;
|
|||
using Elsa.MongoDb.Modules.Management;
|
||||
using Elsa.MongoDb.Modules.Runtime;
|
||||
using Elsa.WorkflowServer.Web;
|
||||
using Fluid;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Proto.Persistence.Sqlite;
|
||||
using Proto.Persistence.SqlServer;
|
||||
|
||||
const bool useMongoDb = false;
|
||||
const bool useSqlServer = false;
|
||||
const bool useDapper = true;
|
||||
const bool useProtoActor = true;
|
||||
const bool useHangfire = false;
|
||||
|
||||
|
|
@ -26,8 +27,8 @@ var services = builder.Services;
|
|||
var configuration = builder.Configuration;
|
||||
var identitySection = configuration.GetSection("Identity");
|
||||
var identityTokenSection = identitySection.GetSection("Tokens");
|
||||
var sqliteConnectionString = configuration.GetConnectionString("Sqlite");
|
||||
var sqlServerConnectionString = configuration.GetConnectionString("SqlServer");
|
||||
var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!;
|
||||
var sqlServerConnectionString = configuration.GetConnectionString("SqlServer")!;
|
||||
var mongoDbConnectionString = configuration.GetConnectionString("MongoDb")!;
|
||||
|
||||
// Add Elsa services.
|
||||
|
|
@ -37,6 +38,19 @@ services
|
|||
if(useMongoDb)
|
||||
elsa.UseMongoDb(mongoDbConnectionString);
|
||||
|
||||
if(useDapper)
|
||||
elsa.UseDapper(dapper =>
|
||||
{
|
||||
dapper.UseMigrations();
|
||||
dapper.DbConnectionProvider = sp =>
|
||||
{
|
||||
if(useSqlServer)
|
||||
return new SqlServerDbConnectionProvider(sqlServerConnectionString!);
|
||||
else
|
||||
return new SqliteDbConnectionProvider(sqliteConnectionString);
|
||||
};
|
||||
});
|
||||
|
||||
if (useHangfire)
|
||||
elsa.UseHangfire();
|
||||
|
||||
|
|
@ -49,6 +63,8 @@ services
|
|||
{
|
||||
if(useMongoDb)
|
||||
identity.UseMongoDb();
|
||||
else if (useDapper)
|
||||
identity.UseDapper();
|
||||
else
|
||||
identity.UseEntityFrameworkCore(ef =>
|
||||
{
|
||||
|
|
@ -69,6 +85,8 @@ services
|
|||
{
|
||||
if(useMongoDb)
|
||||
management.UseMongoDb();
|
||||
else if (useDapper)
|
||||
management.UseDapper();
|
||||
else
|
||||
management.UseEntityFrameworkCore(ef =>
|
||||
{
|
||||
|
|
@ -86,6 +104,8 @@ services
|
|||
{
|
||||
if(useMongoDb)
|
||||
runtime.UseMongoDb();
|
||||
else if (useDapper)
|
||||
runtime.UseDapper();
|
||||
else
|
||||
runtime.UseEntityFrameworkCore(ef =>
|
||||
{
|
||||
|
|
@ -118,7 +138,7 @@ services
|
|||
.UseWorkflowsApi(api => api.AddFastEndpointsAssembly<Program>())
|
||||
.UseRealTimeWorkflows()
|
||||
.UseJavaScript(js => js.JintOptions = options => options.AllowClrAccess = true)
|
||||
.UseLiquid(liquid => liquid.FluidOptions = options => options.Encoder = NullEncoder.Default)
|
||||
.UseLiquid(liquid => liquid.FluidOptions = options => options.Encoder = HtmlEncoder.Default)
|
||||
.UseHttp(http => http.HttpEndpointAuthorizationHandler = sp => sp.GetRequiredService<AllowAnonymousHttpEndpointAuthorizationHandler>())
|
||||
.UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
"Tokens": {
|
||||
"SigningKey": "secret-signing-key",
|
||||
"AccessTokenLifetime": "1:00:00:00",
|
||||
"RefreshTokenLifetime": "1:00:10:00"
|
||||
"RefreshTokenLifetime": "7:00:00:00"
|
||||
},
|
||||
"Roles": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public class Initial : Migration
|
|||
.WithColumn("Id").AsString().PrimaryKey()
|
||||
.WithColumn("DefinitionId").AsString().NotNullable()
|
||||
.WithColumn("Name").AsString().Nullable()
|
||||
.WithColumn("ToolVersion").AsString().Nullable()
|
||||
.WithColumn("Description").AsString().Nullable()
|
||||
.WithColumn("ProviderName").AsString().Nullable()
|
||||
.WithColumn("MaterializerName").AsString().NotNullable()
|
||||
|
|
|
|||
|
|
@ -68,7 +68,10 @@ public class Initial : Migration
|
|||
.WithColumn("Source").AsString().Nullable()
|
||||
.WithColumn("SerializedActivityState").AsString().Nullable()
|
||||
.WithColumn("SerializedPayload").AsString().Nullable()
|
||||
.WithColumn("Timestamp").AsDateTimeOffset().NotNullable();
|
||||
.WithColumn("SerializedException").AsString().Nullable()
|
||||
.WithColumn("Timestamp").AsDateTimeOffset().NotNullable()
|
||||
.WithColumn("Sequence").AsInt64().NotNullable()
|
||||
;
|
||||
|
||||
IfDatabase("Sqlite")
|
||||
.Create
|
||||
|
|
@ -90,8 +93,11 @@ public class Initial : Migration
|
|||
.WithColumn("Source").AsString().Nullable()
|
||||
.WithColumn("SerializedActivityState").AsString().Nullable()
|
||||
.WithColumn("SerializedPayload").AsString().Nullable()
|
||||
.WithColumn("SerializedOutputs").AsString().Nullable()
|
||||
.WithColumn("SerializedException").AsString().Nullable()
|
||||
.WithColumn("Timestamp").AsDateTime2().NotNullable()
|
||||
.WithColumn("Sequence").AsInt64().NotNullable();
|
||||
.WithColumn("Sequence").AsInt64().NotNullable()
|
||||
;
|
||||
|
||||
IfDatabase("SqlServer", "Oracle", "MySql", "Postgres")
|
||||
.Create
|
||||
|
|
@ -104,7 +110,7 @@ public class Initial : Migration
|
|||
.WithColumn("ActivityName").AsString().Nullable()
|
||||
.WithColumn("SerializedActivityState").AsString().Nullable()
|
||||
.WithColumn("SerializedPayload").AsString().Nullable()
|
||||
.WithColumn("SerializedOutput").AsString().Nullable()
|
||||
.WithColumn("SerializedOutputs").AsString().Nullable()
|
||||
.WithColumn("SerializedException").AsString().Nullable()
|
||||
.WithColumn("StartedAt").AsDateTimeOffset().NotNullable()
|
||||
.WithColumn("CompletedAt").AsDateTimeOffset().Nullable()
|
||||
|
|
@ -121,7 +127,10 @@ public class Initial : Migration
|
|||
.WithColumn("ActivityType").AsString().NotNullable()
|
||||
.WithColumn("ActivityTypeVersion").AsInt32().NotNullable()
|
||||
.WithColumn("ActivityName").AsString().Nullable()
|
||||
.WithColumn("ActivityState").AsString().Nullable()
|
||||
.WithColumn("SerializedActivityState").AsString().Nullable()
|
||||
.WithColumn("SerializedPayload").AsString().Nullable()
|
||||
.WithColumn("SerializedOutputs").AsString().Nullable()
|
||||
.WithColumn("SerializedException").AsString().Nullable()
|
||||
.WithColumn("StartedAt").AsDateTime2().NotNullable()
|
||||
.WithColumn("CompletedAt").AsDateTime2().Nullable()
|
||||
.WithColumn("HasBookmarks").AsBoolean().NotNullable()
|
||||
|
|
@ -133,11 +142,12 @@ public class Initial : Migration
|
|||
.Table("WorkflowInboxMessages")
|
||||
.WithColumn("Id").AsString().PrimaryKey()
|
||||
.WithColumn("ActivityTypeName").AsString().NotNullable()
|
||||
.WithColumn("WorkflowInstanceId").AsString().NotNullable()
|
||||
.WithColumn("WorkflowInstanceId").AsString().Nullable()
|
||||
.WithColumn("ActivityInstanceId").AsString().Nullable()
|
||||
.WithColumn("CorrelationId").AsString().Nullable()
|
||||
.WithColumn("Hash").AsString().Nullable()
|
||||
.WithColumn("BookmarkPayload").AsString()
|
||||
.WithColumn("Input").AsString().Nullable()
|
||||
.WithColumn("Hash").AsString().NotNullable()
|
||||
.WithColumn("SerializedBookmarkPayload").AsString()
|
||||
.WithColumn("SerializedInput").AsString().Nullable()
|
||||
.WithColumn("CreatedAt").AsDateTimeOffset()
|
||||
.WithColumn("ExpiresAt").AsDateTimeOffset()
|
||||
;
|
||||
|
|
@ -147,11 +157,12 @@ public class Initial : Migration
|
|||
.Table("WorkflowInboxMessages")
|
||||
.WithColumn("Id").AsString().PrimaryKey()
|
||||
.WithColumn("ActivityTypeName").AsString().NotNullable()
|
||||
.WithColumn("WorkflowInstanceId").AsString().NotNullable()
|
||||
.WithColumn("WorkflowInstanceId").AsString().Nullable()
|
||||
.WithColumn("ActivityInstanceId").AsString().Nullable()
|
||||
.WithColumn("CorrelationId").AsString().Nullable()
|
||||
.WithColumn("Hash").AsString().Nullable()
|
||||
.WithColumn("BookmarkPayload").AsString()
|
||||
.WithColumn("Input").AsString().Nullable()
|
||||
.WithColumn("Hash").AsString().NotNullable()
|
||||
.WithColumn("SerializedBookmarkPayload").AsString()
|
||||
.WithColumn("SerializedInput").AsString().Nullable()
|
||||
.WithColumn("CreatedAt").AsDateTime2()
|
||||
.WithColumn("ExpiresAt").AsDateTime2()
|
||||
;
|
||||
|
|
|
|||
|
|
@ -53,28 +53,28 @@ public abstract class SqlDialectBase : ISqlDialect
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string Skip(int count) => $"OFFSET {count}";
|
||||
public virtual string Skip(int count) => $"offset {count}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string Take(int count) => $"LIMIT {count}";
|
||||
public virtual string Take(int count) => $"limit {count}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Insert(string table, string[] fields)
|
||||
public string Insert(string table, string[] fields, Func<string, string>? getParamName = default)
|
||||
{
|
||||
getParamName ??= x => x;
|
||||
var fieldList = string.Join(", ", fields);
|
||||
var fieldParamNames = fields.Select(x => $"@{x}");
|
||||
var fieldParamNames = fields.Select(x => $"@{getParamName(x)}");
|
||||
var fieldParamList = string.Join(", ", fieldParamNames);
|
||||
return $"INSERT INTO {table} ({fieldList}) VALUES ({fieldParamList});";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string Upsert(string table, string primaryKeyField, string[] fields)
|
||||
public virtual string Upsert(string table, string primaryKeyField, string[] fields, Func<string, string>? getParamName = default)
|
||||
{
|
||||
getParamName ??= x => x;
|
||||
var fieldList = string.Join(", ", fields);
|
||||
var fieldParamNames = fields.Select(x => $"@{x}");
|
||||
var fieldParamNames = fields.Select(x => $"@{getParamName(x)}");
|
||||
var fieldParamList = string.Join(", ", fieldParamNames);
|
||||
//var updateList = string.Join(", ", fields.Select(x => $"{x} = @{x}"));
|
||||
//return $"insert into {table} ({fieldList}) values ({fieldParamList}) on conflict(id) do update set {updateList}";
|
||||
return $"INSERT OR REPLACE INTO {table} ({primaryKeyField}, {fieldList}) VALUES (@{primaryKeyField}, {fieldParamList});";
|
||||
return $"INSERT OR REPLACE INTO {table} ({primaryKeyField}, {fieldList}) VALUES (@{getParamName(primaryKeyField)}, {fieldParamList});";
|
||||
}
|
||||
}
|
||||
|
|
@ -101,15 +101,17 @@ public interface ISqlDialect
|
|||
/// </summary>
|
||||
/// <param name="table">The table.</param>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="getParamName">An optional function to get the parameter name.</param>
|
||||
/// <returns>The query.</returns>
|
||||
string Insert(string table, string[] fields);
|
||||
|
||||
string Insert(string table, string[] fields, Func<string, string>? getParamName = default);
|
||||
|
||||
/// <summary>
|
||||
/// Builds an UPSERT query.
|
||||
/// </summary>
|
||||
/// <param name="table">The table.</param>
|
||||
/// <param name="primaryKeyField">The primary key field.</param>
|
||||
/// <param name="fields">The fields.</param>
|
||||
/// <param name="getParamName">An optional function to get the parameter name.</param>
|
||||
/// <returns>The query.</returns>
|
||||
string Upsert(string table, string primaryKeyField, string[] fields);
|
||||
string Upsert(string table, string primaryKeyField, string[] fields, Func<string, string>? getParamName = default);
|
||||
}
|
||||
|
|
@ -70,6 +70,21 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins a DELETE FROM query.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="table">The table.</param>
|
||||
/// <param name="innerQuery">The inner query.</param>
|
||||
public static ParameterizedQuery Delete(this ParameterizedQuery query, string table, ParameterizedQuery innerQuery)
|
||||
{
|
||||
query.Sql.AppendLine(query.Dialect.Delete(table));
|
||||
query.Sql.AppendLine("and rowid in (");
|
||||
query.Sql.AppendLine(innerQuery.Sql.ToString());
|
||||
query.Sql.AppendLine(")");
|
||||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins a SELECT COUNT(*) FROM query.
|
||||
/// </summary>
|
||||
|
|
@ -122,7 +137,7 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Appends an IS NULL clause to the query.
|
||||
/// </summary>
|
||||
|
|
@ -133,7 +148,7 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
query.Sql.AppendLine(query.Dialect.IsNull(field));
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Appends an IS NOT NULL clause to the query.
|
||||
/// </summary>
|
||||
|
|
@ -262,7 +277,7 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
{
|
||||
if (!orderFields.Any())
|
||||
return query;
|
||||
|
||||
|
||||
var clauses = string.Join(",", orderFields.Select(x => $"{x.Field} {(x.Direction == OrderDirection.Ascending ? "asc" : "desc")}"));
|
||||
query.Sql.AppendLine($"order by {clauses}");
|
||||
return query;
|
||||
|
|
@ -314,22 +329,25 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
/// <param name="table">The table.</param>
|
||||
/// <param name="primaryKeyField">The primary key field.</param>
|
||||
/// <param name="record">The record.</param>
|
||||
public static ParameterizedQuery Upsert(this ParameterizedQuery query, string table, string primaryKeyField, object record)
|
||||
/// <param name="getParameterName">An optional function to get the parameter name.</param>
|
||||
public static ParameterizedQuery Upsert(this ParameterizedQuery query, string table, string primaryKeyField, object record, Func<string, string>? getParameterName = default)
|
||||
{
|
||||
var fields = record.GetType().GetProperties()
|
||||
.Where(x => x.CanRead && x.Name != primaryKeyField)
|
||||
.Select(x => x.Name)
|
||||
.ToArray();
|
||||
|
||||
query.Sql.AppendLine(query.Dialect.Upsert(table, primaryKeyField, fields));
|
||||
|
||||
getParameterName ??= x => x;
|
||||
|
||||
query.Sql.AppendLine(query.Dialect.Upsert(table, primaryKeyField, fields, getParameterName));
|
||||
|
||||
var primaryKeyValue = record.GetType().GetProperty(primaryKeyField)?.GetValue(record);
|
||||
query.Parameters.Add($"@{primaryKeyField}", primaryKeyValue);
|
||||
|
||||
query.Parameters.Add($"@{getParameterName(primaryKeyField)}", primaryKeyValue);
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var value = record.GetType().GetProperty(field)?.GetValue(record);
|
||||
query.Parameters.Add($"@{field}", value);
|
||||
query.Parameters.Add($"@{getParameterName(field)}", value);
|
||||
}
|
||||
|
||||
return query;
|
||||
|
|
@ -341,18 +359,20 @@ public static class ParameterizedQueryBuilderExtensions
|
|||
/// <param name="query">The query.</param>
|
||||
/// <param name="table">The table.</param>
|
||||
/// <param name="record">The record.</param>
|
||||
public static ParameterizedQuery Insert(this ParameterizedQuery query, string table, object record)
|
||||
/// <param name="getParameterName">An optional function to get the parameter name.</param>
|
||||
public static ParameterizedQuery Insert(this ParameterizedQuery query, string table, object record, Func<string, string>? getParameterName = default)
|
||||
{
|
||||
var fields = record.GetType().GetProperties()
|
||||
.Select(x => x.Name)
|
||||
.ToArray();
|
||||
|
||||
query.Sql.AppendLine(query.Dialect.Insert(table, fields));
|
||||
getParameterName ??= x => x;
|
||||
query.Sql.AppendLine(query.Dialect.Insert(table, fields, getParameterName));
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var value = record.GetType().GetProperty(field)?.GetValue(record);
|
||||
query.Parameters.Add($"@{field}", value);
|
||||
query.Parameters.Add($"@{getParameterName(field)}", value);
|
||||
}
|
||||
|
||||
return query;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public class DapperFeature : FeatureBase
|
|||
/// </summary>
|
||||
public Func<IServiceProvider, IDbConnectionProvider> DbConnectionProvider { get; set; } = _ => new SqliteDbConnectionProvider();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Apply()
|
||||
{
|
||||
Services.AddSingleton(DbConnectionProvider);
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ internal class WorkflowDefinitionRecord
|
|||
public int Version { get; set; } = 1;
|
||||
public bool IsLatest { get; set; }
|
||||
public bool IsPublished { get; set; }
|
||||
public bool IsReadonly { get; set; } = false;
|
||||
}
|
||||
|
|
@ -195,6 +195,7 @@ public class DapperWorkflowDefinitionStore : IWorkflowDefinitionStore
|
|||
Description = source.Description,
|
||||
IsPublished = source.IsPublished,
|
||||
IsLatest = source.IsLatest,
|
||||
IsReadonly = source.IsReadonly,
|
||||
CreatedAt = source.CreatedAt,
|
||||
StringData = source.StringData,
|
||||
Options = props.Options,
|
||||
|
|
@ -232,6 +233,7 @@ public class DapperWorkflowDefinitionStore : IWorkflowDefinitionStore
|
|||
IsPublished = source.IsPublished,
|
||||
IsLatest = source.IsLatest,
|
||||
CreatedAt = source.CreatedAt,
|
||||
IsReadonly = source.IsReadonly,
|
||||
StringData = source.StringData,
|
||||
Props = _payloadSerializer.Serialize(props),
|
||||
MaterializerName = source.MaterializerName,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using Elsa.Dapper.Features;
|
||||
using Elsa.Dapper.Modules.Runtime.Stores;
|
||||
using Elsa.Dapper.Services;
|
||||
using Elsa.Features.Abstractions;
|
||||
using Elsa.Features.Attributes;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.Workflows.Runtime.Entities;
|
||||
using Elsa.Workflows.Runtime.Features;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ internal class WorkflowExecutionLogRecordRecord
|
|||
public string? ActivityName { get; set; } = default!;
|
||||
public string NodeId { get; set; } = default!;
|
||||
public DateTimeOffset Timestamp { get; set; }
|
||||
public long Sequence { get; set; }
|
||||
public string? EventName { get; set; }
|
||||
public string? Message { get; set; }
|
||||
public string? Source { get; set; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class WorkflowInboxMessageRecord
|
|||
/// <summary>
|
||||
/// An optional bookmark payload that can be used to filter the workflow instances to deliver the message to.
|
||||
/// </summary>
|
||||
public string BookmarkPayload { get; set; } = default!;
|
||||
public string SerializedBookmarkPayload { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The hash of the bookmark.
|
||||
|
|
@ -43,7 +43,7 @@ public class WorkflowInboxMessageRecord
|
|||
/// <summary>
|
||||
/// An optional set of inputs to deliver to the workflow instance.
|
||||
/// </summary>
|
||||
public string? Input { get; set; }
|
||||
public string? SerializedInput { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date and time the message was created.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using Elsa.Dapper.Contracts;
|
||||
using Elsa.Dapper.Extensions;
|
||||
using Elsa.Dapper.Models;
|
||||
using Elsa.Dapper.Modules.Runtime.Records;
|
||||
|
|
@ -18,7 +19,7 @@ namespace Elsa.Dapper.Modules.Runtime.Stores;
|
|||
/// </summary>
|
||||
public class DapperActivityExecutionRecordStore : IActivityExecutionStore
|
||||
{
|
||||
private const string TableName = "WorkflowExecutionLogRecords";
|
||||
private const string TableName = "ActivityExecutionRecords";
|
||||
private const string PrimaryKeyName = "Id";
|
||||
private readonly IPayloadSerializer _payloadSerializer;
|
||||
private readonly ISafeSerializer _safeSerializer;
|
||||
|
|
@ -27,11 +28,11 @@ public class DapperActivityExecutionRecordStore : IActivityExecutionStore
|
|||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DapperActivityExecutionRecordStore"/> class.
|
||||
/// </summary>
|
||||
public DapperActivityExecutionRecordStore(IPayloadSerializer payloadSerializer, ISafeSerializer safeSerializer, Store<ActivityExecutionRecordRecord> store)
|
||||
public DapperActivityExecutionRecordStore(IDbConnectionProvider dbConnectionProvider, IPayloadSerializer payloadSerializer, ISafeSerializer safeSerializer)
|
||||
{
|
||||
_payloadSerializer = payloadSerializer;
|
||||
_safeSerializer = safeSerializer;
|
||||
_store = store;
|
||||
_store = new Store<ActivityExecutionRecordRecord>(dbConnectionProvider, TableName, PrimaryKeyName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -83,7 +84,7 @@ public class DapperActivityExecutionRecordStore : IActivityExecutionStore
|
|||
|
||||
if (filter.Completed != null)
|
||||
{
|
||||
if(filter.Completed == true)
|
||||
if (filter.Completed == true)
|
||||
query.IsNotNull(nameof(ActivityExecutionRecordRecord.CompletedAt));
|
||||
else
|
||||
query.IsNull(nameof(ActivityExecutionRecordRecord.CompletedAt));
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ public class DapperWorkflowExecutionLogStore : IWorkflowExecutionLogStore
|
|||
ActivityName = source.ActivityName,
|
||||
NodeId = source.NodeId,
|
||||
Timestamp = source.Timestamp,
|
||||
Sequence = source.Sequence,
|
||||
EventName = source.EventName,
|
||||
Message = source.Message,
|
||||
Source = source.Source,
|
||||
|
|
@ -146,6 +147,7 @@ public class DapperWorkflowExecutionLogStore : IWorkflowExecutionLogStore
|
|||
ActivityName = source.ActivityName,
|
||||
NodeId = source.NodeId,
|
||||
Timestamp = source.Timestamp,
|
||||
Sequence = source.Sequence,
|
||||
EventName = source.EventName,
|
||||
Message = source.Message,
|
||||
Source = source.Source,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public class DapperWorkflowInboxMessageStore : IWorkflowInboxMessageStore
|
|||
clauses.Add(clause);
|
||||
}
|
||||
|
||||
var clausesSql = string.Join(" OR ", $"({clauses.Select(x => x.Sql)})");
|
||||
var clausesSql = string.Join(" OR ", clauses.Select(x => x.Sql.ToString()));
|
||||
query.Sql.AppendLine(clausesSql);
|
||||
}
|
||||
|
||||
|
|
@ -99,8 +99,8 @@ public class DapperWorkflowInboxMessageStore : IWorkflowInboxMessageStore
|
|||
CorrelationId = source.CorrelationId,
|
||||
ActivityInstanceId = source.ActivityInstanceId,
|
||||
Hash = source.Hash,
|
||||
BookmarkPayload = _payloadSerializer.Serialize(source.BookmarkPayload),
|
||||
Input = source.Input != null ? _payloadSerializer.Serialize(source.Input) : default,
|
||||
SerializedBookmarkPayload = _payloadSerializer.Serialize(source.BookmarkPayload),
|
||||
SerializedInput = source.Input != null ? _payloadSerializer.Serialize(source.Input) : default,
|
||||
CreatedAt = source.CreatedAt,
|
||||
ExpiresAt = source.ExpiresAt,
|
||||
};
|
||||
|
|
@ -116,8 +116,8 @@ public class DapperWorkflowInboxMessageStore : IWorkflowInboxMessageStore
|
|||
CorrelationId = source.CorrelationId,
|
||||
ActivityInstanceId = source.ActivityInstanceId,
|
||||
Hash = source.Hash,
|
||||
BookmarkPayload = _payloadSerializer.Deserialize(source.BookmarkPayload),
|
||||
Input = source.Input != null ? _payloadSerializer.Deserialize<Dictionary<string, object>>(source.Input) : default,
|
||||
BookmarkPayload = _payloadSerializer.Deserialize(source.SerializedBookmarkPayload),
|
||||
Input = source.SerializedInput != null ? _payloadSerializer.Deserialize<Dictionary<string, object>>(source.SerializedInput) : default,
|
||||
CreatedAt = source.CreatedAt,
|
||||
ExpiresAt = source.ExpiresAt,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
using System.Data;
|
||||
using Elsa.Dapper.Contracts;
|
||||
using Elsa.Dapper.Dialects;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace Elsa.Dapper.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a SQLite connection to the database.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public class SqlServerDbConnectionProvider : IDbConnectionProvider
|
||||
{
|
||||
private readonly string _connectionString = "Server=localhost;Database=Elsa;Trusted_Connection=True;";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqlServerDbConnectionProvider"/> class.
|
||||
/// </summary>
|
||||
public SqlServerDbConnectionProvider()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqlServerDbConnectionProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The connection string to use.</param>
|
||||
public SqlServerDbConnectionProvider(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetConnectionString() =>_connectionString;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDbConnection GetConnection()
|
||||
{
|
||||
return new SqlConnection
|
||||
{
|
||||
ConnectionString = GetConnectionString()
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISqlDialect Dialect => new SqliteDialect();
|
||||
}
|
||||
|
|
@ -12,8 +12,26 @@ namespace Elsa.Dapper.Services;
|
|||
[PublicAPI]
|
||||
public class SqliteDbConnectionProvider : IDbConnectionProvider
|
||||
{
|
||||
private readonly string _connectionString = "Data Source=elsa.dapper.db";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteDbConnectionProvider"/> class.
|
||||
/// </summary>
|
||||
public SqliteDbConnectionProvider()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqliteDbConnectionProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The connection string to use.</param>
|
||||
public SqliteDbConnectionProvider(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetConnectionString() => "Data Source=elsa.dapper.db";
|
||||
public string GetConnectionString() =>_connectionString;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDbConnection GetConnection()
|
||||
|
|
|
|||
|
|
@ -205,9 +205,14 @@ public class Store<T> where T : notnull
|
|||
public async Task SaveManyAsync(IEnumerable<T> records, string primaryKey = "Id", CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = new ParameterizedQuery(_dbConnectionProvider.Dialect);
|
||||
var currentIndex = 0;
|
||||
|
||||
foreach (var record in records)
|
||||
query.Upsert(TableName, primaryKey, record);
|
||||
{
|
||||
var index = currentIndex;
|
||||
query.Upsert(TableName, primaryKey, record, field => $"{field}_{index}");
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
using var connection = _dbConnectionProvider.GetConnection();
|
||||
await query.ExecuteAsync(connection);
|
||||
|
|
@ -249,11 +254,13 @@ public class Store<T> where T : notnull
|
|||
/// <returns>The number of records deleted.</returns>
|
||||
public async Task<long> DeleteAsync(Action<ParameterizedQuery> filter, PageArgs pageArgs, IEnumerable<OrderField> orderFields, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var selectQuery = _dbConnectionProvider.CreateQuery().From(TableName, "rowid");
|
||||
filter(selectQuery);
|
||||
selectQuery = selectQuery.OrderBy(orderFields.ToArray()).Page(pageArgs);
|
||||
|
||||
var deleteQuery = _dbConnectionProvider.CreateQuery().Delete(TableName, selectQuery);
|
||||
using var connection = _dbConnectionProvider.GetConnection();
|
||||
var query = _dbConnectionProvider.CreateQuery().Delete(TableName);
|
||||
filter(query);
|
||||
query = query.OrderBy(orderFields.ToArray()).Page(pageArgs);
|
||||
return await query.ExecuteAsync(connection);
|
||||
return await deleteQuery.ExecuteAsync(connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ internal class List : ElsaEndpoint<Request, PagedListResponse<WorkflowDefinition
|
|||
{
|
||||
var order = new WorkflowDefinitionOrder<string>
|
||||
{
|
||||
KeySelector = p => p.Name ?? string.Empty,
|
||||
KeySelector = p => p.Name!,
|
||||
Direction = direction
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue