@@ -24,9 +24,12 @@ namespace DotNetCore.CAP | |||||
services.AddSingleton<CapDatabaseStorageMarkerService>(); | services.AddSingleton<CapDatabaseStorageMarkerService>(); | ||||
services.AddSingleton<IStorage, PostgreSqlStorage>(); | services.AddSingleton<IStorage, PostgreSqlStorage>(); | ||||
services.AddSingleton<IStorageConnection, PostgreSqlStorageConnection>(); | services.AddSingleton<IStorageConnection, PostgreSqlStorageConnection>(); | ||||
services.AddScoped<ICapPublisher, CapPublisher>(); | |||||
services.AddScoped<ICallbackPublisher, CapPublisher>(); | |||||
services.AddScoped<ICapPublisher, PostgreSqlPublisher>(); | |||||
services.AddScoped<ICallbackPublisher, PostgreSqlPublisher>(); | |||||
services.AddTransient<ICollectProcessor, PostgreSqlCollectProcessor>(); | services.AddTransient<ICollectProcessor, PostgreSqlCollectProcessor>(); | ||||
services.AddTransient<CapTransactionBase, PostgreSqlCapTransaction>(); | |||||
AddSingletonPostgreSqlOptions(services); | AddSingletonPostgreSqlOptions(services); | ||||
} | } | ||||
@@ -1,6 +1,7 @@ | |||||
// Copyright (c) .NET Core Community. All rights reserved. | // Copyright (c) .NET Core Community. All rights reserved. | ||||
// Licensed under the MIT License. See License.txt in the project root for license information. | // Licensed under the MIT License. See License.txt in the project root for license information. | ||||
// ReSharper disable once CheckNamespace | |||||
namespace DotNetCore.CAP | namespace DotNetCore.CAP | ||||
{ | { | ||||
public class PostgreSqlOptions : EFOptions | public class PostgreSqlOptions : EFOptions | ||||
@@ -1,85 +0,0 @@ | |||||
// Copyright (c) .NET Core Community. All rights reserved. | |||||
// Licensed under the MIT License. See License.txt in the project root for license information. | |||||
using System; | |||||
using System.Data; | |||||
using System.Threading.Tasks; | |||||
using Dapper; | |||||
using DotNetCore.CAP.Abstractions; | |||||
using DotNetCore.CAP.Models; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using Microsoft.EntityFrameworkCore.Storage; | |||||
using Microsoft.Extensions.Logging; | |||||
using Npgsql; | |||||
namespace DotNetCore.CAP.PostgreSql | |||||
{ | |||||
public class CapPublisher : CapPublisherBase, ICallbackPublisher | |||||
{ | |||||
private readonly DbContext _dbContext; | |||||
private readonly PostgreSqlOptions _options; | |||||
public CapPublisher(ILogger<CapPublisher> logger, IDispatcher dispatcher, | |||||
IServiceProvider provider, PostgreSqlOptions options) | |||||
: base(logger, dispatcher) | |||||
{ | |||||
ServiceProvider = provider; | |||||
_options = options; | |||||
if (_options.DbContextType != null) | |||||
{ | |||||
IsUsingEF = true; | |||||
_dbContext = (DbContext) ServiceProvider.GetService(_options.DbContextType); | |||||
} | |||||
} | |||||
public async Task PublishCallbackAsync(CapPublishedMessage message) | |||||
{ | |||||
using (var conn = new NpgsqlConnection(_options.ConnectionString)) | |||||
{ | |||||
var id = await conn.ExecuteScalarAsync<int>(PrepareSql(), message); | |||||
message.Id = id; | |||||
Enqueue(message); | |||||
} | |||||
} | |||||
protected override void PrepareConnectionForEF() | |||||
{ | |||||
DbConnection = _dbContext.Database.GetDbConnection(); | |||||
var dbContextTransaction = _dbContext.Database.CurrentTransaction; | |||||
var dbTrans = dbContextTransaction?.GetDbTransaction(); | |||||
//DbTransaction is dispose in original | |||||
if (dbTrans?.Connection == null) | |||||
{ | |||||
IsCapOpenedTrans = true; | |||||
dbContextTransaction?.Dispose(); | |||||
dbContextTransaction = _dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted); | |||||
dbTrans = dbContextTransaction.GetDbTransaction(); | |||||
} | |||||
DbTransaction = dbTrans; | |||||
} | |||||
protected override int Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, | |||||
CapPublishedMessage message) | |||||
{ | |||||
return dbConnection.ExecuteScalar<int>(PrepareSql(), message, dbTransaction); | |||||
} | |||||
protected override Task<int> ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, | |||||
CapPublishedMessage message) | |||||
{ | |||||
return dbConnection.ExecuteScalarAsync<int>(PrepareSql(), message, dbTransaction); | |||||
} | |||||
#region private methods | |||||
private string PrepareSql() | |||||
{ | |||||
return | |||||
$"INSERT INTO \"{_options.Schema}\".\"published\" (\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING \"Id\";"; | |||||
} | |||||
#endregion private methods | |||||
} | |||||
} |
@@ -0,0 +1,93 @@ | |||||
// Copyright (c) .NET Core Community. All rights reserved. | |||||
// Licensed under the MIT License. See License.txt in the project root for license information. | |||||
using System; | |||||
using System.Data; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using Dapper; | |||||
using DotNetCore.CAP.Abstractions; | |||||
using DotNetCore.CAP.Models; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using Microsoft.EntityFrameworkCore.Storage; | |||||
using Npgsql; | |||||
namespace DotNetCore.CAP.PostgreSql | |||||
{ | |||||
public class PostgreSqlPublisher : CapPublisherBase, ICallbackPublisher | |||||
{ | |||||
private readonly DbContext _dbContext; | |||||
private readonly PostgreSqlOptions _options; | |||||
private readonly bool _isUsingEF; | |||||
private NpgsqlConnection _connection; | |||||
public PostgreSqlPublisher(IServiceProvider provider, PostgreSqlOptions options): base(provider) | |||||
{ | |||||
_options = options; | |||||
if (_options.DbContextType == null) | |||||
{ | |||||
return; | |||||
} | |||||
_isUsingEF = true; | |||||
_dbContext = (DbContext)ServiceProvider.GetService(_options.DbContextType); | |||||
} | |||||
public async Task PublishCallbackAsync(CapPublishedMessage message) | |||||
{ | |||||
await PublishAsyncInternal(message); | |||||
} | |||||
protected override Task ExecuteAsync(CapPublishedMessage message, ICapTransaction transaction, | |||||
CancellationToken cancel = default(CancellationToken)) | |||||
{ | |||||
var dbTrans = transaction.DbTransaction as IDbTransaction; | |||||
if (dbTrans == null && transaction.DbTransaction is IDbContextTransaction dbContextTrans) | |||||
{ | |||||
dbTrans = dbContextTrans.GetDbTransaction(); | |||||
} | |||||
var conn = dbTrans?.Connection; | |||||
return conn.ExecuteAsync(PrepareSql(), message, dbTrans); | |||||
} | |||||
protected override object GetDbTransaction() | |||||
{ | |||||
if (_isUsingEF) | |||||
{ | |||||
var dbContextTransaction = _dbContext.Database.CurrentTransaction; | |||||
if (dbContextTransaction == null) | |||||
{ | |||||
return InitDbConnection(); | |||||
} | |||||
return dbContextTransaction; | |||||
} | |||||
return InitDbConnection(); | |||||
} | |||||
#region private methods | |||||
private string PrepareSql() | |||||
{ | |||||
return | |||||
$"INSERT INTO \"{_options.Schema}\".\"published\" (\"Id\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Id,@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; | |||||
} | |||||
private IDbTransaction InitDbConnection() | |||||
{ | |||||
_connection = new NpgsqlConnection(_options.ConnectionString); | |||||
_connection.Open(); | |||||
return _connection.BeginTransaction(IsolationLevel.ReadCommitted); | |||||
} | |||||
#endregion private methods | |||||
public void Dispose() | |||||
{ | |||||
_dbContext?.Dispose(); | |||||
_connection?.Dispose(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,72 @@ | |||||
using System.Data; | |||||
using System.Diagnostics; | |||||
using Microsoft.EntityFrameworkCore.Storage; | |||||
// ReSharper disable once CheckNamespace | |||||
namespace DotNetCore.CAP | |||||
{ | |||||
public class PostgreSqlCapTransaction : CapTransactionBase | |||||
{ | |||||
public PostgreSqlCapTransaction(IDispatcher dispatcher) : base(dispatcher) { } | |||||
public override void Commit() | |||||
{ | |||||
Debug.Assert(DbTransaction != null); | |||||
switch (DbTransaction) | |||||
{ | |||||
case IDbTransaction dbTransaction: | |||||
dbTransaction.Commit(); | |||||
break; | |||||
case IDbContextTransaction dbContextTransaction: | |||||
dbContextTransaction.Commit(); | |||||
break; | |||||
} | |||||
Flush(); | |||||
} | |||||
public override void Rollback() | |||||
{ | |||||
Debug.Assert(DbTransaction != null); | |||||
switch (DbTransaction) | |||||
{ | |||||
case IDbTransaction dbTransaction: | |||||
dbTransaction.Rollback(); | |||||
break; | |||||
case IDbContextTransaction dbContextTransaction: | |||||
dbContextTransaction.Rollback(); | |||||
break; | |||||
} | |||||
} | |||||
public override void Dispose() | |||||
{ | |||||
(DbTransaction as IDbTransaction)?.Dispose(); | |||||
} | |||||
} | |||||
public static class CapTransactionExtensions | |||||
{ | |||||
public static ICapTransaction Begin(this ICapTransaction transaction, | |||||
IDbTransaction dbTransaction, bool autoCommit = false) | |||||
{ | |||||
transaction.DbTransaction = dbTransaction; | |||||
transaction.AutoCommit = autoCommit; | |||||
return transaction; | |||||
} | |||||
public static ICapTransaction Begin(this ICapTransaction transaction, | |||||
IDbContextTransaction dbTransaction, bool autoCommit = false) | |||||
{ | |||||
transaction.DbTransaction = dbTransaction; | |||||
transaction.AutoCommit = autoCommit; | |||||
return transaction; | |||||
} | |||||
} | |||||
} |
@@ -100,10 +100,8 @@ namespace DotNetCore.CAP.PostgreSql | |||||
var batchSql = $@" | var batchSql = $@" | ||||
CREATE SCHEMA IF NOT EXISTS ""{schema}""; | CREATE SCHEMA IF NOT EXISTS ""{schema}""; | ||||
DROP TABLE IF EXISTS ""{schema}"".""queue""; | |||||
CREATE TABLE IF NOT EXISTS ""{schema}"".""received""( | CREATE TABLE IF NOT EXISTS ""{schema}"".""received""( | ||||
""Id"" SERIAL PRIMARY KEY NOT NULL, | |||||
""Id"" BIGINT PRIMARY KEY NOT NULL, | |||||
""Name"" VARCHAR(200) NOT NULL, | ""Name"" VARCHAR(200) NOT NULL, | ||||
""Group"" VARCHAR(200) NULL, | ""Group"" VARCHAR(200) NULL, | ||||
""Content"" TEXT NULL, | ""Content"" TEXT NULL, | ||||
@@ -114,7 +112,7 @@ CREATE TABLE IF NOT EXISTS ""{schema}"".""received""( | |||||
); | ); | ||||
CREATE TABLE IF NOT EXISTS ""{schema}"".""published""( | CREATE TABLE IF NOT EXISTS ""{schema}"".""published""( | ||||
""Id"" SERIAL PRIMARY KEY NOT NULL, | |||||
""Id"" BIGINT PRIMARY KEY NOT NULL, | |||||
""Name"" VARCHAR(200) NOT NULL, | ""Name"" VARCHAR(200) NOT NULL, | ||||
""Content"" TEXT NULL, | ""Content"" TEXT NULL, | ||||
""Retries"" INT NOT NULL, | ""Retries"" INT NOT NULL, |
@@ -28,7 +28,7 @@ namespace DotNetCore.CAP.PostgreSql | |||||
return new PostgreSqlStorageTransaction(this); | return new PostgreSqlStorageTransaction(this); | ||||
} | } | ||||
public async Task<CapPublishedMessage> GetPublishedMessageAsync(int id) | |||||
public async Task<CapPublishedMessage> GetPublishedMessageAsync(long id) | |||||
{ | { | ||||
var sql = $"SELECT * FROM \"{Options.Schema}\".\"published\" WHERE \"Id\"={id} FOR UPDATE SKIP LOCKED"; | var sql = $"SELECT * FROM \"{Options.Schema}\".\"published\" WHERE \"Id\"={id} FOR UPDATE SKIP LOCKED"; | ||||
@@ -50,7 +50,7 @@ namespace DotNetCore.CAP.PostgreSql | |||||
} | } | ||||
} | } | ||||
public async Task<int> StoreReceivedMessageAsync(CapReceivedMessage message) | |||||
public void StoreReceivedMessage(CapReceivedMessage message) | |||||
{ | { | ||||
if (message == null) | if (message == null) | ||||
{ | { | ||||
@@ -58,15 +58,15 @@ namespace DotNetCore.CAP.PostgreSql | |||||
} | } | ||||
var sql = | var sql = | ||||
$"INSERT INTO \"{Options.Schema}\".\"received\"(\"Name\",\"Group\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING \"Id\";"; | |||||
$"INSERT INTO \"{Options.Schema}\".\"received\"(\"Id\",\"Name\",\"Group\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Id,@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING \"Id\";"; | |||||
using (var connection = new NpgsqlConnection(Options.ConnectionString)) | using (var connection = new NpgsqlConnection(Options.ConnectionString)) | ||||
{ | { | ||||
return await connection.ExecuteScalarAsync<int>(sql, message); | |||||
connection.Execute(sql, message); | |||||
} | } | ||||
} | } | ||||
public async Task<CapReceivedMessage> GetReceivedMessageAsync(int id) | |||||
public async Task<CapReceivedMessage> GetReceivedMessageAsync(long id) | |||||
{ | { | ||||
var sql = $"SELECT * FROM \"{Options.Schema}\".\"received\" WHERE \"Id\"={id} FOR UPDATE SKIP LOCKED"; | var sql = $"SELECT * FROM \"{Options.Schema}\".\"received\" WHERE \"Id\"={id} FOR UPDATE SKIP LOCKED"; | ||||
using (var connection = new NpgsqlConnection(Options.ConnectionString)) | using (var connection = new NpgsqlConnection(Options.ConnectionString)) | ||||
@@ -90,7 +90,7 @@ namespace DotNetCore.CAP.PostgreSql | |||||
{ | { | ||||
} | } | ||||
public bool ChangePublishedState(int messageId, string state) | |||||
public bool ChangePublishedState(long messageId, string state) | |||||
{ | { | ||||
var sql = | var sql = | ||||
$"UPDATE \"{Options.Schema}\".\"published\" SET \"Retries\"=\"Retries\"+1,\"ExpiresAt\"=NULL,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; | $"UPDATE \"{Options.Schema}\".\"published\" SET \"Retries\"=\"Retries\"+1,\"ExpiresAt\"=NULL,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; | ||||
@@ -101,7 +101,7 @@ namespace DotNetCore.CAP.PostgreSql | |||||
} | } | ||||
} | } | ||||
public bool ChangeReceivedState(int messageId, string state) | |||||
public bool ChangeReceivedState(long messageId, string state) | |||||
{ | { | ||||
var sql = | var sql = | ||||
$"UPDATE \"{Options.Schema}\".\"received\" SET \"Retries\"=\"Retries\"+1,\"ExpiresAt\"=NULL,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; | $"UPDATE \"{Options.Schema}\".\"received\" SET \"Retries\"=\"Retries\"+1,\"ExpiresAt\"=NULL,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; |
@@ -35,9 +35,7 @@ namespace DotNetCore.CAP.PostgreSql | |||||
} | } | ||||
var sql = | var sql = | ||||
$@"UPDATE ""{ | |||||
_schema | |||||
}"".""published"" SET ""Retries""=@Retries,""Content""= @Content,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; | |||||
$@"UPDATE ""{_schema}"".""published"" SET ""Retries""=@Retries,""Content""= @Content,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; | |||||
_dbConnection.Execute(sql, message, _dbTransaction); | _dbConnection.Execute(sql, message, _dbTransaction); | ||||
} | } | ||||
@@ -66,29 +64,5 @@ namespace DotNetCore.CAP.PostgreSql | |||||
_dbTransaction.Dispose(); | _dbTransaction.Dispose(); | ||||
_dbConnection.Dispose(); | _dbConnection.Dispose(); | ||||
} | } | ||||
public void EnqueueMessage(CapPublishedMessage message) | |||||
{ | |||||
if (message == null) | |||||
{ | |||||
throw new ArgumentNullException(nameof(message)); | |||||
} | |||||
var sql = $@"INSERT INTO ""{_schema}"".""queue"" values(@MessageId,@MessageType);"; | |||||
_dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Publish}, | |||||
_dbTransaction); | |||||
} | |||||
public void EnqueueMessage(CapReceivedMessage message) | |||||
{ | |||||
if (message == null) | |||||
{ | |||||
throw new ArgumentNullException(nameof(message)); | |||||
} | |||||
var sql = $@"INSERT INTO ""{_schema}"".""queue"" values(@MessageId,@MessageType);"; | |||||
_dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Subscribe}, | |||||
_dbTransaction); | |||||
} | |||||
} | } | ||||
} | } |
@@ -22,17 +22,18 @@ namespace DotNetCore.CAP.PostgreSql.Test | |||||
[Fact] | [Fact] | ||||
public async Task GetPublishedMessageAsync_Test() | public async Task GetPublishedMessageAsync_Test() | ||||
{ | { | ||||
var sql = @"INSERT INTO ""cap"".""published""(""Name"",""Content"",""Retries"",""Added"",""ExpiresAt"",""StatusName"") VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING ""Id"";"; | |||||
var sql = @"INSERT INTO ""cap"".""published""(""Id"",""Name"",""Content"",""Retries"",""Added"",""ExpiresAt"",""StatusName"") VALUES(@Id,@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; | |||||
var insertedId = SnowflakeId.Default().NextId(); | |||||
var publishMessage = new CapPublishedMessage | var publishMessage = new CapPublishedMessage | ||||
{ | { | ||||
Id = insertedId, | |||||
Name = "PostgreSqlStorageConnectionTest", | Name = "PostgreSqlStorageConnectionTest", | ||||
Content = "", | Content = "", | ||||
StatusName = StatusName.Scheduled | StatusName = StatusName.Scheduled | ||||
}; | }; | ||||
var insertedId = default(int); | |||||
using (var connection = ConnectionUtil.CreateConnection()) | using (var connection = ConnectionUtil.CreateConnection()) | ||||
{ | { | ||||
insertedId = connection.QueryFirst<int>(sql, publishMessage); | |||||
await connection.ExecuteAsync(sql, publishMessage); | |||||
} | } | ||||
var message = await _storage.GetPublishedMessageAsync(insertedId); | var message = await _storage.GetPublishedMessageAsync(insertedId); | ||||
Assert.NotNull(message); | Assert.NotNull(message); | ||||
@@ -41,10 +42,11 @@ namespace DotNetCore.CAP.PostgreSql.Test | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public async Task StoreReceivedMessageAsync_Test() | |||||
public void StoreReceivedMessageAsync_Test() | |||||
{ | { | ||||
var receivedMessage = new CapReceivedMessage | var receivedMessage = new CapReceivedMessage | ||||
{ | { | ||||
Id = SnowflakeId.Default().NextId(), | |||||
Name = "PostgreSqlStorageConnectionTest", | Name = "PostgreSqlStorageConnectionTest", | ||||
Content = "", | Content = "", | ||||
Group = "mygroup", | Group = "mygroup", | ||||
@@ -54,7 +56,7 @@ namespace DotNetCore.CAP.PostgreSql.Test | |||||
Exception exception = null; | Exception exception = null; | ||||
try | try | ||||
{ | { | ||||
await _storage.StoreReceivedMessageAsync(receivedMessage); | |||||
_storage.StoreReceivedMessage(receivedMessage); | |||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
@@ -67,19 +69,21 @@ namespace DotNetCore.CAP.PostgreSql.Test | |||||
public async Task GetReceivedMessageAsync_Test() | public async Task GetReceivedMessageAsync_Test() | ||||
{ | { | ||||
var sql = $@" | var sql = $@" | ||||
INSERT INTO ""cap"".""received""(""Name"",""Group"",""Content"",""Retries"",""Added"",""ExpiresAt"",""StatusName"") | |||||
VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING ""Id"";"; | |||||
INSERT INTO ""cap"".""received""(""Id"",""Name"",""Group"",""Content"",""Retries"",""Added"",""ExpiresAt"",""StatusName"") | |||||
VALUES(@Id,@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; | |||||
var insertedId = SnowflakeId.Default().NextId(); | |||||
var receivedMessage = new CapReceivedMessage | var receivedMessage = new CapReceivedMessage | ||||
{ | { | ||||
Id= insertedId, | |||||
Name = "PostgreSqlStorageConnectionTest", | Name = "PostgreSqlStorageConnectionTest", | ||||
Content = "", | Content = "", | ||||
Group = "mygroup", | Group = "mygroup", | ||||
StatusName = StatusName.Scheduled | StatusName = StatusName.Scheduled | ||||
}; | }; | ||||
var insertedId = default(int); | |||||
using (var connection = ConnectionUtil.CreateConnection()) | using (var connection = ConnectionUtil.CreateConnection()) | ||||
{ | { | ||||
insertedId = connection.QueryFirst<int>(sql, receivedMessage); | |||||
await connection.ExecuteAsync(sql, receivedMessage); | |||||
} | } | ||||
var message = await _storage.GetReceivedMessageAsync(insertedId); | var message = await _storage.GetReceivedMessageAsync(insertedId); | ||||
@@ -6,13 +6,11 @@ namespace DotNetCore.CAP.PostgreSql.Test | |||||
[Collection("postgresql")] | [Collection("postgresql")] | ||||
public class SqlServerStorageTest : DatabaseTestHost | public class SqlServerStorageTest : DatabaseTestHost | ||||
{ | { | ||||
private readonly string _dbName; | |||||
private readonly string _masterDbConnectionString; | private readonly string _masterDbConnectionString; | ||||
private readonly string _dbConnectionString; | private readonly string _dbConnectionString; | ||||
public SqlServerStorageTest() | public SqlServerStorageTest() | ||||
{ | { | ||||
_dbName = ConnectionUtil.GetDatabaseName(); | |||||
_masterDbConnectionString = ConnectionUtil.GetMasterConnectionString(); | _masterDbConnectionString = ConnectionUtil.GetMasterConnectionString(); | ||||
_dbConnectionString = ConnectionUtil.GetConnectionString(); | _dbConnectionString = ConnectionUtil.GetConnectionString(); | ||||
} | } | ||||