From 52a29970716a9a4c914d56956367cab50d39fad2 Mon Sep 17 00:00:00 2001 From: Eric Nguyen Date: Sat, 30 Dec 2023 13:31:19 +0700 Subject: [PATCH] fix sqlite --- .../json/init-new-dbcontext-databases.json | 238 ++++++++++++++++++ .../shared/json/system-databases.json | 233 ++++++++++++++++- .../Controllers/SharedApiController.cs | 8 +- .../mix.tenancy/Controllers/InitController.cs | 1 - .../mix.repodb/Services/MixDbDataService.cs | 20 +- .../Services/BaseHubClientService.cs | 10 +- .../Services/LogStreamHubClientService.cs | 5 +- .../Services/MixDbCommandHubClientService.cs | 5 +- .../Services/PortalHubClientService.cs | 9 +- .../Services/JsonConfigurationServiceBase.cs | 2 +- .../mix.shared/Services/MixEndpointService.cs | 3 + 11 files changed, 507 insertions(+), 27 deletions(-) create mode 100644 src/applications/mixcore/wwwroot/default-mixcontent/shared/json/init-new-dbcontext-databases.json diff --git a/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/init-new-dbcontext-databases.json b/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/init-new-dbcontext-databases.json new file mode 100644 index 000000000..c3df180a7 --- /dev/null +++ b/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/init-new-dbcontext-databases.json @@ -0,0 +1,238 @@ +{ + "databases": [ + { + "systemName": "MixDatabaseAssociation", + "displayName": "Data Relationship", + "description": null, + "type": "Service", + "readPermissions": "[\"Owner\"]", + "createPermissions": "[\"Owner\"]", + "updatePermissions": "[\"Owner\"]", + "deletePermissions": "[\"Owner\"]", + "selfManaged": false, + "mixDatabaseColumns": null, + "sourceRelationships": null, + "destinateRelationships": null, + "id": 25, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": "administrator", + "modifiedBy": "administrator", + "priority": 0, + "status": "Published", + "isDeleted": false + } + ], + "columns": [ + { + "systemName": "ParentDatabaseName", + "displayName": "Source Database Name", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Text", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 1, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 2, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ChildDatabaseName", + "displayName": "Destination Database Name", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Text", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 2, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 3, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "GuidParentId", + "displayName": "Guid Source Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Guid", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 3, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 3, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "GuidChildId", + "displayName": "Destination Guid Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Guid", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 4, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 4, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ParentId", + "displayName": "Source Integer Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Integer", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 5, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 5, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ChildId", + "displayName": "Destination Integer Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Integer", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 6, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 6, + "status": "Published", + "isDeleted": false + } + ] +} diff --git a/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/system-databases.json b/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/system-databases.json index 79f2730e7..3a708e53d 100644 --- a/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/system-databases.json +++ b/src/applications/mixcore/wwwroot/default-mixcontent/shared/json/system-databases.json @@ -1,5 +1,27 @@ { "databases": [ + { + "systemName": "MixDatabaseAssociation", + "displayName": "Data Relationship", + "description": null, + "type": "Service", + "readPermissions": "[\"Owner\"]", + "createPermissions": "[\"Owner\"]", + "updatePermissions": "[\"Owner\"]", + "deletePermissions": "[\"Owner\"]", + "selfManaged": false, + "mixDatabaseColumns": null, + "sourceRelationships": null, + "destinateRelationships": null, + "id": 25, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": "administrator", + "modifiedBy": "administrator", + "priority": 0, + "status": "Published", + "isDeleted": false + }, { "systemName": "warehouse", "displayName": "Warehouse", @@ -354,7 +376,216 @@ } ], "columns": [ - + { + "systemName": "ParentDatabaseName", + "displayName": "Source Database Name", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Text", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 1, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 2, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ChildDatabaseName", + "displayName": "Destination Database Name", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Text", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 2, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 3, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "GuidParentId", + "displayName": "Guid Source Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Guid", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 3, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 3, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "GuidChildId", + "displayName": "Destination Guid Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Guid", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 4, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 4, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ParentId", + "displayName": "Source Integer Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Integer", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 5, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 5, + "status": "Published", + "isDeleted": false + }, + { + "systemName": "ChildId", + "displayName": "Destination Integer Id", + "mixDatabaseName": "MixDatabaseAssociation", + "dataType": "Integer", + "configurations": { + "isUnique": false, + "isRequire": false, + "isEncrypt": false, + "isSelect": false, + "maxLength": null, + "belongTo": null, + "optionsConfigurationName": null, + "allowedValues": null, + "upload": { + "arrayAccepts": [], + "accepts": "", + "width": null, + "height": null, + "isCrop": false + } + }, + "referenceId": null, + "defaultValue": null, + "mixDatabaseId": 25, + "mixDatabase": null, + "id": 6, + "createdDateTime": "2023-06-15T08:56:50", + "lastModified": null, + "createdBy": null, + "modifiedBy": null, + "priority": 6, + "status": "Published", + "isDeleted": false + }, { "systemName": "postId", "displayName": "Post Id", diff --git a/src/modules/mix.common/Controllers/SharedApiController.cs b/src/modules/mix.common/Controllers/SharedApiController.cs index 33c51a021..765f61ddd 100644 --- a/src/modules/mix.common/Controllers/SharedApiController.cs +++ b/src/modules/mix.common/Controllers/SharedApiController.cs @@ -84,15 +84,9 @@ public ActionResult DecryptMessage(CryptoMessageDto encryptMessage) [HttpGet] [MixAuthorize(roles: $"{MixRoles.SuperAdmin},{MixRoles.Owner}")] [Route("stop-application")] - public async Task StopApplication() + public void StopApplication() { _applicationLifetime.StopApplication(); - string _currentProcess = Path.GetFullPath(Process.GetCurrentProcess().MainModule.FileName); - - Process.Start(_currentProcess); - - await Task.FromResult(0); - return Ok(DateTime.UtcNow); } [HttpGet] diff --git a/src/modules/mix.tenancy/Controllers/InitController.cs b/src/modules/mix.tenancy/Controllers/InitController.cs index ebdaa5016..dc9f4f0ff 100644 --- a/src/modules/mix.tenancy/Controllers/InitController.cs +++ b/src/modules/mix.tenancy/Controllers/InitController.cs @@ -97,7 +97,6 @@ public async Task> InitTenant([FromBody] InitCmsDto model) await _mixTenantService.Reload(); Session.Put(MixRequestQueryKeywords.Tenant, _mixTenantService.AllTenants.First()); _mixEndpointService.SetDefaultDomain($"https://{model.PrimaryDomain}"); - return Ok(); } catch (Exception ex) diff --git a/src/platform/mix.repodb/Services/MixDbDataService.cs b/src/platform/mix.repodb/Services/MixDbDataService.cs index 36d11e670..a3d64a06d 100644 --- a/src/platform/mix.repodb/Services/MixDbDataService.cs +++ b/src/platform/mix.repodb/Services/MixDbDataService.cs @@ -33,7 +33,6 @@ public class MixDbDataService : TenantServiceBase, IMixDbDataService { private const string LastModifiedFieldName = "LastModified"; private readonly MixRepoDbRepository _repository; - private readonly MixRepoDbRepository _associationRepository; private readonly IMixMemoryCacheService _memoryCache; private RepoDbMixDatabaseViewModel? _mixDb; #region Properties @@ -65,8 +64,6 @@ public MixDbDataService( { _cmsUow = uow; _repository = repository; - _associationRepository = new MixRepoDbRepository(cache, databaseService, uow); - _associationRepository.InitTableName(nameof(MixDatabaseAssociation)); _memoryCache = memoryCache; } @@ -130,12 +127,13 @@ public async Task> GetMyData(string tableName, Sear return default; } + _repository.InitTableName(GetRelationshipDbName()); foreach (var item in database.Relationships) { if (loadNestedData) { List associationQueries = GetAssociationQueries(item.SourceDatabaseName, item.DestinateDatabaseName, id); - var associations = await _associationRepository.GetListByAsync(associationQueries); + var associations = await _repository.GetListByAsync(associationQueries); if (associations is null) { continue; @@ -247,7 +245,12 @@ public async Task DeleteData(string tableName, int id) #endregion #region Helper - + private string GetRelationshipDbName() + { + return _mixDb.MixDatabaseContextId.HasValue + ? $"{_mixDb.MixDatabaseContext.SystemName}_{MixDatabaseNames.DATA_RELATIONSHIP}" + : MixDatabaseNames.DATA_RELATIONSHIP; + } public static string GetCacheFolder(string databaseName) { return $"{MixFolders.MixDbCacheFolder}/{databaseName}"; @@ -261,11 +264,11 @@ private async Task LoadNestedData(string tableName, JObject data) { return; } - + _repository.InitTableName(GetRelationshipDbName()); foreach (var item in database.Relationships) { List queries = GetAssociationQueries(item.SourceDatabaseName, item.DestinateDatabaseName, data.Value("id")); - var associations = await _associationRepository.GetListByAsync(queries); + var associations = await _repository.GetListByAsync(queries); if (associations is { Count: > 0 }) { var nestedIds = JArray.FromObject(associations).Select(m => m.Value(ChildIdFieldName)).ToList(); @@ -294,12 +297,13 @@ private async Task> GetResult(string tableName, IEn var data = ReflectionHelper.ParseObject(item); if (loadNestedData) { + _repository.InitTableName(GetRelationshipDbName()); foreach (var rel in database.Relationships) { var id = data.Value("id"); List nestedQueries = GetAssociationQueries(rel.SourceDatabaseName, rel.DestinateDatabaseName, id); - var associations = await _associationRepository.GetListByAsync(nestedQueries); + var associations = await _repository.GetListByAsync(nestedQueries); if (associations is { Count: > 0 }) { var nestedIds = JArray.FromObject(associations).Select(m => m.Value(ChildIdFieldName)).ToList(); diff --git a/src/platform/mix.service/Services/BaseHubClientService.cs b/src/platform/mix.service/Services/BaseHubClientService.cs index 2f29568eb..a69849bc1 100644 --- a/src/platform/mix.service/Services/BaseHubClientService.cs +++ b/src/platform/mix.service/Services/BaseHubClientService.cs @@ -14,6 +14,7 @@ using Mix.SignalR.Interfaces; using Mix.Heart.Helpers; using Mix.Heart.Extensions; +using Microsoft.Extensions.Logging; namespace Mix.Service.Services { @@ -21,13 +22,15 @@ public abstract class BaseHubClientService : IHubClientService { public HubConnection Connection { get; set; } protected string HubName; + protected ILogger _logger; protected string AccessToken; public bool IsStarted => Connection != null; protected readonly MixEndpointService MixEndpointService; - protected BaseHubClientService(string hub, MixEndpointService mixEndpointService) + protected BaseHubClientService(string hub, MixEndpointService mixEndpointService, ILogger logger) { HubName = hub; MixEndpointService = mixEndpointService; + _logger = logger; } public Task SendMessageAsync(string title, string description, object data, MessageType messageType = MessageType.Info) @@ -49,10 +52,11 @@ public async Task SendPrivateMessageAsync(SignalRMessageModel message, string co { await StartConnection(); await Connection.InvokeAsync(HubMethods.SendPrivateMessage, message, connectionId, selfReceive); + _logger.LogInformation("Start SignalR client successfully"); } else { - Console.WriteLine("Cannot Start SignalR Hub: MixEndpointService.Messenger is null or empty"); + _logger.LogWarning("Cannot Start SignalR Hub: MixEndpointService.Messenger is null or empty"); } } catch (Exception ex) @@ -72,7 +76,7 @@ public async Task SendMessageAsync(SignalRMessageModel message) } else { - Console.WriteLine("Cannot Start SignalR Hub: MixEndpointService.Messenger is null or empty"); + _logger.LogWarning($"{_logger.GetType().FullName}: Cannot Start SignalR Hub: MixEndpointService.Messenger is null or empty"); } } catch (Exception ex) diff --git a/src/platform/mix.service/Services/LogStreamHubClientService.cs b/src/platform/mix.service/Services/LogStreamHubClientService.cs index 6a279ee2f..3cbd3957d 100644 --- a/src/platform/mix.service/Services/LogStreamHubClientService.cs +++ b/src/platform/mix.service/Services/LogStreamHubClientService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Mix.Shared.Services; using Mix.SignalR.Constants; using Mix.SignalR.Interfaces; @@ -9,8 +10,8 @@ namespace Mix.Service.Services { public class LogStreamHubClientService : BaseHubClientService, ILogStreamHubClientService { - public LogStreamHubClientService(MixEndpointService mixEndpointService) - : base(HubEndpoints.LogStreamHub, mixEndpointService) + public LogStreamHubClientService(MixEndpointService mixEndpointService, ILogger logger) + : base(HubEndpoints.LogStreamHub, mixEndpointService, logger) { } diff --git a/src/platform/mix.service/Services/MixDbCommandHubClientService.cs b/src/platform/mix.service/Services/MixDbCommandHubClientService.cs index f3cc58a26..ddeff5590 100644 --- a/src/platform/mix.service/Services/MixDbCommandHubClientService.cs +++ b/src/platform/mix.service/Services/MixDbCommandHubClientService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Mix.Shared.Services; using Mix.SignalR.Constants; using Mix.SignalR.Interfaces; @@ -9,8 +10,8 @@ namespace Mix.Service.Services { public class MixDbCommandHubClientService : BaseHubClientService, IMixDbCommandHubClientService { - public MixDbCommandHubClientService(MixEndpointService mixEndpointService) - : base(HubEndpoints.MixDbCommandHub, mixEndpointService) + public MixDbCommandHubClientService(MixEndpointService mixEndpointService, ILogger logger) + : base(HubEndpoints.MixDbCommandHub, mixEndpointService, logger) { } diff --git a/src/platform/mix.service/Services/PortalHubClientService.cs b/src/platform/mix.service/Services/PortalHubClientService.cs index 1228086be..aacdefcb4 100644 --- a/src/platform/mix.service/Services/PortalHubClientService.cs +++ b/src/platform/mix.service/Services/PortalHubClientService.cs @@ -1,6 +1,7 @@ using MessagePack; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Mix.Constant.Constants; using Mix.Database.Entities.Cms; using Mix.Heart.Enums; @@ -28,8 +29,12 @@ public class PortalHubClientService : BaseHubClientService, IPortalHubClientServ private readonly IServiceProvider _serviceProvider; private readonly IMixTenantService _mixTenantService; - public PortalHubClientService(IServiceProvider serviceProvider, MixEndpointService mixEndpointService, IMixTenantService mixTenantService) - : base(HubEndpoints.PortalHub, mixEndpointService) + public PortalHubClientService( + IServiceProvider serviceProvider, + MixEndpointService mixEndpointService, + IMixTenantService mixTenantService, + ILogger logger) + : base(HubEndpoints.PortalHub, mixEndpointService, logger) { _serviceProvider = serviceProvider; _mixTenantService = mixTenantService; diff --git a/src/platform/mix.shared/Services/JsonConfigurationServiceBase.cs b/src/platform/mix.shared/Services/JsonConfigurationServiceBase.cs index 625f089a5..d6fe07e69 100644 --- a/src/platform/mix.shared/Services/JsonConfigurationServiceBase.cs +++ b/src/platform/mix.shared/Services/JsonConfigurationServiceBase.cs @@ -39,7 +39,7 @@ public T GetEnumConfig(string name) public void SetConfig(string name, T value) { - AppSettings[name] = object.Equals(value, default(T)) ? JToken.FromObject(value) : null; + AppSettings[name] = object.Equals(value, default(T)) ? JToken.FromObject(value) : value.ToString(); SaveSettings(); } diff --git a/src/platform/mix.shared/Services/MixEndpointService.cs b/src/platform/mix.shared/Services/MixEndpointService.cs index ba113599f..78671fa2b 100644 --- a/src/platform/mix.shared/Services/MixEndpointService.cs +++ b/src/platform/mix.shared/Services/MixEndpointService.cs @@ -8,6 +8,9 @@ public MixEndpointService() : base(MixAppConfigFilePaths.Endpoint) public void SetDefaultDomain(string domain) { + Messenger ??= domain; + MixMq ??= domain; + Mixcore ??= domain; } protected override void LoadAppSettings()