20 changed files with 381 additions and 29 deletions
@ -0,0 +1,18 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Auditing; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class TenantConnectionStringCheckInput |
|||
{ |
|||
[Required] |
|||
public string Provider { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[DisableAuditing] |
|||
[DynamicStringLength(typeof(TenantConnectionStringConsts), nameof(TenantConnectionStringConsts.MaxValueLength))] |
|||
public string ConnectionString { get; set; } |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class TenantConnectionStringCheckResultDto |
|||
{ |
|||
public bool Connected { get; set; } |
|||
public TenantConnectionStringCheckResultDto() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public TenantConnectionStringCheckResultDto(bool connected) |
|||
{ |
|||
Connected = connected; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,28 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net9.0</TargetFramework> |
|||
<AssemblyName>LINGYUN.Abp.Saas.DbChecker</AssemblyName> |
|||
<PackageId>LINGYUN.Abp.Saas.DbChecker</PackageId> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="MySqlConnector" /> |
|||
<PackageReference Include="Oracle.ManagedDataAccess.Core" /> |
|||
<PackageReference Include="Npgsql" /> |
|||
<PackageReference Include="Microsoft.Data.SqlClient" /> |
|||
<PackageReference Include="Microsoft.Data.Sqlite.Core" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Saas.Domain\LINGYUN.Abp.Saas.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,24 @@ |
|||
using LINGYUN.Abp.Saas.MySql; |
|||
using LINGYUN.Abp.Saas.Oracle; |
|||
using LINGYUN.Abp.Saas.PostgreSql; |
|||
using LINGYUN.Abp.Saas.Sqlite; |
|||
using LINGYUN.Abp.Saas.SqlServer; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Saas; |
|||
|
|||
[DependsOn(typeof(AbpSaasDomainModule))] |
|||
public class AbpSaasDbCheckerModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpSaasConnectionStringCheckOptions>(options => |
|||
{ |
|||
options.ConnectionStringCheckers["mysql"] = new MySqlConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["oracle"] = new OracleConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["postgres"] = new NpgsqlConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["sqlite"] = new SqliteConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["sqlserver"] = new SqlServerConnectionStringChecker(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using MySqlConnector; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.MySql; |
|||
|
|||
public class MySqlConnectionStringChecker : IDataBaseConnectionStringChecker |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new MySqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectionLifeTime = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.Database; |
|||
connString.Database = "mysql"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new MySqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Oracle.ManagedDataAccess.Client; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Oracle; |
|||
|
|||
public class OracleConnectionStringChecker : IDataBaseConnectionStringChecker |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new OracleConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectionTimeout = 1 |
|||
}; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new OracleConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Npgsql; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.PostgreSql; |
|||
|
|||
public class NpgsqlConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new NpgsqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
Timeout = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.Database; |
|||
connString.Database = "postgres"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new NpgsqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName!); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Microsoft.Data.SqlClient; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.SqlServer; |
|||
|
|||
public class SqlServerConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new SqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectTimeout = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.InitialCatalog; |
|||
connString.InitialCatalog = "master"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new SqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Microsoft.Data.Sqlite; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Sqlite; |
|||
|
|||
public class SqliteConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new SqliteConnection(connectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,15 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.Saas; |
|||
|
|||
public class AbpSaasConnectionStringCheckOptions |
|||
{ |
|||
public IDictionary<string, IDataBaseConnectionStringChecker> ConnectionStringCheckers { get; } |
|||
|
|||
public AbpSaasConnectionStringCheckOptions() |
|||
{ |
|||
ConnectionStringCheckers = new Dictionary<string, IDataBaseConnectionStringChecker>(StringComparer.InvariantCultureIgnoreCase); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class DataBaseConnectionStringCheckResult : AbpConnectionStringCheckResult |
|||
{ |
|||
public Exception Error { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public interface IDataBaseConnectionStringChecker |
|||
{ |
|||
Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString); |
|||
} |
|||
Loading…
Reference in new issue