diff --git a/docs/content/user-guide/en/storage/postgresql.md b/docs/content/user-guide/en/storage/postgresql.md
index 7835b7f3a..04a47fd18 100644
--- a/docs/content/user-guide/en/storage/postgresql.md
+++ b/docs/content/user-guide/en/storage/postgresql.md
@@ -32,10 +32,11 @@ public void ConfigureServices(IServiceCollection services)
#### PostgreSqlOptions
-NAME | DESCRIPTION | TYPE | DEFAULT
-:---|:---|---|:---
-Schema | Database schema | string | cap
-ConnectionString | Database connection string | string |
+NAME | DESCRIPTION | TYPE | DEFAULT
+:---|:---------------------------|----------------------|:---
+Schema | Database schema | string | cap
+ConnectionString | Database connection string | string |
+DataSource | [Data source](https://www.npgsql.org/doc/basic-usage.html#data-source) | [NpgsqlDataSource](https://www.npgsql.org/doc/api/Npgsql.NpgsqlDataSource.html) |
## Publish with transaction
diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
index 225d2aa07..10b735f80 100644
--- a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
+++ b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
@@ -6,6 +6,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using Npgsql;
// ReSharper disable once CheckNamespace
namespace DotNetCore.CAP;
@@ -15,7 +16,21 @@ public class PostgreSqlOptions : EFOptions
///
/// Gets or sets the database's connection string that will be used to store database entities.
///
+ [Obsolete("Use .DataSource = NpgsqlDataSource.Create() for same behavior.")]
public string ConnectionString { get; set; } = default!;
+
+ ///
+ /// Gets or sets the Npgsql data source that will be used to store database entities.
+ ///
+ public NpgsqlDataSource? DataSource { get; set; }
+
+ ///
+ /// Creates an Npgsql connection from the configured data source.
+ ///
+ internal NpgsqlConnection CreateConnection()
+ {
+ return DataSource != null ? DataSource.CreateConnection() : new NpgsqlConnection(ConnectionString);
+ }
}
internal class ConfigurePostgreSqlOptions : IConfigureOptions
diff --git a/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs b/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
index 43d0b879c..8a62956c1 100644
--- a/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
+++ b/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
@@ -50,7 +50,7 @@ public async Task AcquireLockAsync(string key, TimeSpan ttl, string instan
{
var sql =
$"UPDATE {_lockName} SET \"Instance\"=@Instance,\"LastLockTime\"=@LastLockTime WHERE \"Key\"=@Key AND \"LastLockTime\" < @TTL;";
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
object[] sqlParams =
{
@@ -67,7 +67,7 @@ public async Task ReleaseLockAsync(string key, string instance, CancellationToke
{
var sql =
$"UPDATE {_lockName} SET \"Instance\"='',\"LastLockTime\"=@LastLockTime WHERE \"Key\"=@Key AND \"Instance\"=@Instance;";
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
object[] sqlParams =
{
@@ -82,7 +82,7 @@ public async Task RenewLockAsync(string key, TimeSpan ttl, string instance, Canc
{
var sql =
$"UPDATE {_lockName} SET \"LastLockTime\"=\"LastLockTime\"+interval '{ttl.TotalSeconds}' second WHERE \"Key\"=@Key AND \"Instance\"=@Instance;";
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
object[] sqlParams =
{
@@ -96,7 +96,7 @@ public async Task ChangePublishStateToDelayedAsync(string[] ids)
{
var sql =
$"UPDATE {_pubName} SET \"StatusName\"='{StatusName.Delayed}' WHERE \"Id\" IN ({string.Join(',', ids)});";
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
await connection.ExecuteNonQueryAsync(sql).ConfigureAwait(false);
}
@@ -140,7 +140,7 @@ public async Task StoreMessageAsync(string name, Message content,
if (transaction == null)
{
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
await connection.ExecuteNonQueryAsync(sql, sqlParams: sqlParams).ConfigureAwait(false);
}
@@ -205,7 +205,7 @@ public async Task StoreReceivedMessageAsync(string name, string g
public async Task DeleteExpiresAsync(string table, DateTime timeout, int batchCount = 1000,
CancellationToken token = default)
{
- var connection = new NpgsqlConnection(_options.Value.ConnectionString);
+ var connection = _options.Value.CreateConnection();
await using var _ = connection.ConfigureAwait(false);
return await connection.ExecuteNonQueryAsync(
$"DELETE FROM {table} WHERE \"Id\" IN (SELECT \"Id\" FROM {table} WHERE \"ExpiresAt\" < @timeout AND (\"StatusName\"='{StatusName.Succeeded}' OR \"StatusName\"='{StatusName.Failed}') LIMIT @batchCount);",
@@ -238,7 +238,7 @@ public async Task ScheduleMessagesOfDelayedAsync(Func