Browse Source

Merge branch 'dev' into issue-3404/L

pull/18855/head
Gizem Mutu Kurt 2 years ago
parent
commit
46c4621457
  1. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  2. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  3. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  4. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
  5. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
  6. 72
      docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md
  7. BIN
      docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/deepl.jpg
  8. 6
      docs/en/Multi-Tenancy.md
  9. 20
      framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs
  10. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs
  11. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs
  12. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs
  13. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs
  14. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs
  15. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js
  16. 12
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs
  17. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor
  18. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  19. 6
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs
  20. 4
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs
  21. 10
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs
  22. 11
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs
  23. 8
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs
  24. 7
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs
  25. 3
      framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs
  26. 3
      framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs
  27. 3
      framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs
  28. 4
      modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor
  29. 4
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor
  30. 4
      modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor
  31. 2
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor
  32. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor
  33. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml
  34. 4
      modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor
  35. 4
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs
  36. 12
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs
  37. 8
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs
  38. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs
  39. 32
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs
  40. 2
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs
  41. 8
      modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs
  42. 8
      modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs
  43. 44
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs
  44. 11
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs
  45. 7
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs
  46. 7
      modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs
  47. 5
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs
  48. 17
      modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs
  49. 9
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs
  50. 6
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs
  51. 7
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
  52. 9
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs
  53. 6
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs
  54. 7
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
  55. 9
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs
  56. 6
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs
  57. 7
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs
  58. 9
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs
  59. 6
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs
  60. 7
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs
  61. 9
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs
  62. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs
  63. 7
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs
  64. 9
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs
  65. 6
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs
  66. 7
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs
  67. 9
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs
  68. 6
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs
  69. 7
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs
  70. 31
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs
  71. 22
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs
  72. 28
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs
  73. 9
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs
  74. 6
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs
  75. 7
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

4
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -592,6 +592,8 @@
"OrganizationId": "Organization Id",
"RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?",
"AutoRenewals": "Auto Renewals",
"OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!"
"OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!",
"DisplayName:DontSendEmailForLicenseExpire": "Don't Send Email For License Expire",
"DontSendEmailForLicenseExpire": "Don't Send Email For License Expire"
}
}

2
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -1130,7 +1130,7 @@
"NameOnCard": "Name on Card",
"BillingDetails": "Billing Details",
"ThereIsNoDeveloper": "There is no developer.",
"CardDetails": "Card Details",
"CardDetails": "Debit/Credit Card Details",
"NoActiveLicence": "You are not eligible for this action! You have no active license."
}
}

2
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json

@ -353,6 +353,8 @@
"BuildSolutionsWithAbp": "Build maintainable .NET solutions by following software development best practices using ABP.",
"BuyOnAmazon": "Buy on Amazon",
"BuyOnPackt": "Buy on Packt",
"BuyOnDangDang": "Buy on DangDang",
"BuyOnJD": "Buy on JD",
"Discounted": "Discounted",
"MasteringAbpFramework_Book_KeyFeatures": "Key Features",
"MasteringAbpFramework_Book_Key_Features_Description_1": "Build robust, maintainable, modular, and scalable software solutions using ABP Framework.",

2
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json

@ -353,6 +353,8 @@
"BuildSolutionsWithAbp": "使用 ABP,遵循软件开发最佳实践,构建可维护的 .NET 解决方案。",
"BuyOnAmazon": "在亚马逊上购买",
"BuyOnPackt": "在 Packt 购买",
"BuyOnDangDang": "在当当网购买",
"BuyOnJD": "在京东上购买",
"Discounted": "折扣",
"MasteringAbpFramework_Book_KeyFeatures": "主要功能",
"MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架构建稳健、可维护、模块化和可扩展的软件解决方案。",

2
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json

@ -353,6 +353,8 @@
"BuildSolutionsWithAbp": "使用 ABP 遵循軟體開發最佳實務來建立可維護的 .NET 解決方案。",
"BuyOnAmazon": "在亞馬遜上購買",
"BuyOnPackt": "在 Packt 上購買",
"BuyOnDangDang": "在當當上購買",
"BuyOnJD": "在京東上購買",
"Discounted": "折扣",
"MasteringAbpFramework_Book_KeyFeatures": "主要特徵",
"MasteringAbpFramework_Book_Key_Features_Description_1": "使用 ABP 框架建構健壯、可維護、模組化和可擴展的軟體解決方案。",

72
docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/Post.md

@ -0,0 +1,72 @@
# Use Deepl to translate localization files
Translating localized text during the development of ABP modules is a boring job. For this reason, we have added the `translate` command to the CLI tool to translate the localization files, but it still requires manual translation of texts by the developer.
Now, we introduce a new way to translate the target language, which is to use the [Deepl](https://www.deepl.com/translator) translation service to translate the target language.
You can use the `translate --online` command in your module directory to translate the target language.
For example, if you have added all `en` localization texts to your module, and you want to translate them to `zh-Hans`, you can run the following command:
```
abp translate -r en -c zh-Hans --online --deepl-auth-key your_auth_key
```
* `-r` parameter is used to specify the source language. It is usually a localized file that you have created.
* `-c` parameter is used to specify the target language. It is usually a language that you want to translate.
* `--online` parameter is used to indicate that the translation is performed from the Deepl service.
* `--deepl-auth-key` parameter is the API key of your Deepl account. You can get it from [here](https://support.deepl.com/hc/en-us/articles/360020695820-Authentication-Key).
The output of the above command is as follows:
```
ABP CLI 8.0.0
Abp translate online...
Target culture: zh-Hans
Reference culture: en
Create translation: Settings => 设置
Create translation: SuccessfullySaved => 成功保存
Create translation: Permission:SettingManagement => 设置管理
Create translation: Permission:Emailing => 发送电子邮件
Create translation: Permission:EmailingTest => 电子邮件测试
Create translation: Permission:TimeZone => 时区
Create translation: SendTestEmail => 发送测试电子邮件
Create translation: SenderEmailAddress => 发件人电子邮件地址
Create translation: TargetEmailAddress => 目标电子邮件地址
Create translation: Subject => 主题
Create translation: Body => 正文
Create translation: TestEmailSubject => 测试电子邮件 {0}
Create translation: TestEmailBody => 在此测试电子邮件正文信息
Create translation: SuccessfullySent => 成功发送
Create translation: Send => 发送
Create translation: Menu:Emailing => 发送电子邮件
Create translation: Menu:TimeZone => 时区
Create translation: DisplayName:Timezone => 时区
Create translation: TimezoneHelpText => 此设置用于应用程序范围或基于租户的设置。
Create translation: SmtpHost => 主机
Create translation: SmtpPort => 端口
Create translation: SmtpUserName => 用户名
Create translation: SmtpPassword => 密码
Create translation: SmtpDomain => 域名
Create translation: SmtpEnableSsl => 启用 ssl
Create translation: SmtpUseDefaultCredentials => 使用默认凭据
Create translation: DefaultFromAddress => 默认地址
Create translation: DefaultFromDisplayName => 显示名称的默认值
Create translation: Feature:SettingManagementGroup => 设置管理
Create translation: Feature:SettingManagementEnable => 启用设置管理
Create translation: Feature:SettingManagementEnableDescription => 在应用程序中启用设置管理系统。
Create translation: Feature:AllowChangingEmailSettings => 允许更改电子邮件设置。
Create translation: Feature:AllowChangingEmailSettingsDescription => 允许更改电子邮件设置。
Write translation json to setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json.
```
The generated `zh-Hans.json` as follow:
![zh-Hans.json](deepl.jpg)
In this example, It only translates one `en.json` to `zh-Hans.json`, but if there are multiple `en.json` files in the module, it will translate all `en.json` files to `zh-Hans.json`.
Of course, the translation is not always correct, you can update the translation in the generated `zh-Hans.json` files.
Enjoy it!

BIN
docs/en/Community-Articles/2024-01-04-CLI-Online-Translate/deepl.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

6
docs/en/Multi-Tenancy.md

@ -394,6 +394,8 @@ app.UseMultiTenancy();
`ITenantStore` is used to get the tenant configuration from a data source.
> Tenant names are not case-sensitive. `ITenantStore` will use the `NormalizedName` parameter to get tenants, You need to use `ITenantNormalizer to normalize tenant names.
#### Tenant Management Module
The [tenant management module](Modules/Tenant-Management) is **included in the startup templates** and implements the `ITenantStore` interface to get the tenants and their configuration from a database. It also provides the necessary functionality and UI to manage the tenants and their connection strings.
@ -408,11 +410,13 @@ The [tenant management module](Modules/Tenant-Management) is **included in the s
"Tenants": [
{
"Id": "446a5211-3d72-4339-9adc-845151f8ada0",
"Name": "tenant1"
"Name": "tenant1",
"NormalizedName": "TENANT1"
},
{
"Id": "25388015-ef1c-4355-9c18-f6b6ddbaf89d",
"Name": "tenant2",
"NormalizedName": "TENANT2",
"ConnectionStrings": {
"Default": "...tenant2's db connection string here..."
}

20
framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorRemoteTenantStore.cs

@ -23,13 +23,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency
Cache = cache;
}
public async Task<TenantConfiguration?> FindAsync(string name)
public async Task<TenantConfiguration?> FindAsync(string normalizedName)
{
var cacheKey = CreateCacheKey(name);
var cacheKey = CreateCacheKey(normalizedName);
var tenantConfiguration = await Cache.GetOrAddAsync(
cacheKey,
async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name))!,
async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName))!,
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
@ -57,13 +57,13 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency
return tenantConfiguration;
}
public TenantConfiguration? Find(string name)
public TenantConfiguration? Find(string normalizedName)
{
var cacheKey = CreateCacheKey(name);
var cacheKey = CreateCacheKey(normalizedName);
var tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name)))!,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(normalizedName)))!,
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
@ -98,16 +98,16 @@ public class MauiBlazorRemoteTenantStore : ITenantStore, ITransientDependency
return null;
}
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!);
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name!, tenantResultDto.NormalizedName!);
}
protected virtual string CreateCacheKey(string tenantName)
protected virtual string CreateCacheKey(string normalizedName)
{
return $"RemoteTenantStore_Name_{tenantName}";
return $"RemoteTenantStore_Name_{normalizedName}";
}
protected virtual string CreateCacheKey(Guid tenantId)
{
return $"RemoteTenantStore_Id_{tenantId:N}";
}
}
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs

@ -29,9 +29,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
Options = options.Value;
}
public async Task<TenantConfiguration?> FindAsync(string name)
public async Task<TenantConfiguration?> FindAsync(string normalizedName)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name);
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName);
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext)
@ -42,7 +42,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
var tenantConfiguration = await Cache.GetAsync(cacheKey);
if (tenantConfiguration == null)
{
await TenantAppService.FindTenantByNameAsync(name);
await TenantAppService.FindTenantByNameAsync(normalizedName);
tenantConfiguration = await Cache.GetAsync(cacheKey);
}
@ -79,9 +79,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
return tenantConfiguration?.Value;
}
public TenantConfiguration? Find(string name)
public TenantConfiguration? Find(string normalizedName)
{
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(name);
var cacheKey = TenantConfigurationCacheItem.CalculateCacheKey(normalizedName);
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is TenantConfigurationCacheItem tenantConfigurationInHttpContext)
@ -92,7 +92,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
var tenantConfiguration = Cache.Get(cacheKey);
if (tenantConfiguration == null)
{
AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(name));
AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(normalizedName));
tenantConfiguration = Cache.Get(cacheKey);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs

@ -11,5 +11,7 @@ public class FindTenantResultDto
public string? Name { get; set; }
public string? NormalizedName { get; set; }
public bool IsActive { get; set; }
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs

@ -90,13 +90,13 @@ public class AbpModalFooterTagHelperService : AbpTagHelperService<AbpModalFooter
return element.ToHtmlString();
}
protected virtual string GetCancelButton()
protected virtual string GetCancelButton(bool isDestructive = false)
{
var element = new TagBuilder("button");
element.Attributes.Add("type", "button");
element.Attributes.Add("data-bs-dismiss", "modal");
element.AddCssClass("btn");
element.AddCssClass("btn-secondary");
element.AddCssClass("btn-outline-primary");
element.InnerHtml.Append(_localizer["Cancel"]);
return element.ToHtmlString();

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs

@ -9,15 +9,17 @@ namespace Pages.Abp.MultiTenancy;
public class AbpTenantAppService : ApplicationService, IAbpTenantAppService
{
protected ITenantStore TenantStore { get; }
protected ITenantNormalizer TenantNormalizer { get; }
public AbpTenantAppService(ITenantStore tenantStore)
public AbpTenantAppService(ITenantStore tenantStore, ITenantNormalizer tenantNormalizer)
{
TenantStore = tenantStore;
TenantNormalizer = tenantNormalizer;
}
public virtual async Task<FindTenantResultDto> FindTenantByNameAsync(string name)
{
var tenant = await TenantStore.FindAsync(name);
var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(name)!);
if (tenant == null)
{
@ -29,6 +31,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService
Success = true,
TenantId = tenant.Id,
Name = tenant.Name,
NormalizedName = tenant.NormalizedName,
IsActive = tenant.IsActive
};
}
@ -47,6 +50,7 @@ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService
Success = true,
TenantId = tenant.Id,
Name = tenant.Name,
NormalizedName = tenant.NormalizedName,
IsActive = tenant.IsActive
};
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs

@ -18,13 +18,16 @@ public class TenantSwitchModalModel : AbpPageModel
public TenantInfoModel Input { get; set; } = default!;
protected ITenantStore TenantStore { get; }
protected ITenantNormalizer TenantNormalizer { get; }
protected AbpAspNetCoreMultiTenancyOptions Options { get; }
public TenantSwitchModalModel(
ITenantStore tenantStore,
ITenantNormalizer tenantNormalizer,
IOptions<AbpAspNetCoreMultiTenancyOptions> options)
{
TenantStore = tenantStore;
TenantNormalizer = tenantNormalizer;
Options = options.Value;
LocalizationResourceType = typeof(AbpUiMultiTenancyResource);
}
@ -45,7 +48,7 @@ public class TenantSwitchModalModel : AbpPageModel
Guid? tenantId = null;
if (!Input.Name.IsNullOrEmpty())
{
var tenant = await TenantStore.FindAsync(Input.Name!);
var tenant = await TenantStore.FindAsync(TenantNormalizer.NormalizeName(Input.Name!)!);
if (tenant == null)
{
throw new UserFriendlyException(L["GivenTenantIsNotExist", Input.Name!]);

7
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js

@ -103,6 +103,13 @@ var abp = abp || {};
abp.libs.sweetAlert.config.default.confirmButtonText = l('Ok');
abp.libs.sweetAlert.config.default.denyButtonText = l('No');
abp.libs.sweetAlert.config.default.cancelButtonText = l('Cancel');
abp.libs.sweetAlert.config.default.buttonsStyling = false;
abp.libs.sweetAlert.config.default.customClass = {
confirmButton: "btn btn-primary",
cancelButton: "btn btn-outline-primary mx-2",
denyButton: "btn btn-outline-primary mx-2"
};
abp.libs.sweetAlert.config.confirm.title = l('AreYouSure');
abp.libs.sweetAlert.config.confirm.confirmButtonText = l('Yes');
abp.libs.sweetAlert.config.confirm.showCancelButton = true;

12
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
@ -34,7 +33,10 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende
public virtual IFileInfo GetFileInfo(string subpath)
{
Check.NotNullOrEmpty(subpath, nameof(subpath));
if (string.IsNullOrEmpty(subpath))
{
return new NotFoundFileInfo(subpath);
}
if (PathUtils.PathNavigatesAboveRoot(subpath))
{
@ -53,11 +55,9 @@ public class WebContentFileProvider : IWebContentFileProvider, ISingletonDepende
return _fileProvider.GetFileInfo(_rootPath + subpath);
}
public virtual IDirectoryContents GetDirectoryContents([NotNull] string subpath)
public virtual IDirectoryContents GetDirectoryContents(string subpath)
{
Check.NotNullOrEmpty(subpath, nameof(subpath));
if (PathUtils.PathNavigatesAboveRoot(subpath))
if (subpath == null || PathUtils.PathNavigatesAboveRoot(subpath))
{
return NotFoundDirectoryContents.Singleton;
}

2
framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor

@ -22,7 +22,7 @@
<ModalFooter class="d-flex justify-content-center">
@if ( IsConfirmation )
{
<Button Color="Color.Danger" Padding="Padding.Is3.OnX" Margin="Margin.Is1.OnX" Clicked="@OnCancelClicked">
<Button Color="Color.Primary" Outline Padding="Padding.Is3.OnX" Margin="Margin.Is1.OnX" Clicked="@OnCancelClicked">
@if ( Options?.CancelButtonIcon != null )
{
<Icon Name="@Options.CancelButtonIcon" Margin="Margin.Is2.FromEnd" />

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -1,4 +1,4 @@
using System.Text;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Commands.Internal;

6
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantNormalizer.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.MultiTenancy;
public interface ITenantNormalizer
{
string? NormalizeName(string? name);
}

4
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/ITenantStore.cs

@ -5,12 +5,12 @@ namespace Volo.Abp.MultiTenancy;
public interface ITenantStore
{
Task<TenantConfiguration?> FindAsync(string name);
Task<TenantConfiguration?> FindAsync(string normalizedName);
Task<TenantConfiguration?> FindAsync(Guid id);
[Obsolete("Use FindAsync method.")]
TenantConfiguration? Find(string name);
TenantConfiguration? Find(string normalizedName);
[Obsolete("Use FindAsync method.")]
TenantConfiguration? Find(Guid id);

10
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantConfiguration.cs

@ -11,6 +11,8 @@ public class TenantConfiguration
public string Name { get; set; } = default!;
public string NormalizedName { get; set; } = default!;
public ConnectionStrings? ConnectionStrings { get; set; }
public bool IsActive { get; set; }
@ -30,4 +32,12 @@ public class TenantConfiguration
ConnectionStrings = new ConnectionStrings();
}
public TenantConfiguration(Guid id, [NotNull] string name, [NotNull] string normalizedName)
: this(id, name)
{
Check.NotNull(normalizedName, nameof(normalizedName));
NormalizedName = normalizedName;
}
}

11
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/UpperInvariantTenantNormalizer.cs

@ -0,0 +1,11 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MultiTenancy;
public class UpperInvariantTenantNormalizer : ITenantNormalizer, ITransientDependency
{
public virtual string? NormalizeName(string? name)
{
return name?.Normalize().ToUpperInvariant();
}
}

8
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/ConfigurationStore/DefaultTenantStore.cs

@ -16,9 +16,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency
_options = options.CurrentValue;
}
public Task<TenantConfiguration?> FindAsync(string name)
public Task<TenantConfiguration?> FindAsync(string normalizedName)
{
return Task.FromResult(Find(name));
return Task.FromResult(Find(normalizedName));
}
public Task<TenantConfiguration?> FindAsync(Guid id)
@ -26,9 +26,9 @@ public class DefaultTenantStore : ITenantStore, ITransientDependency
return Task.FromResult(Find(id));
}
public TenantConfiguration? Find(string name)
public TenantConfiguration? Find(string normalizedName)
{
return _options.Tenants?.FirstOrDefault(t => t.Name == name);
return _options.Tenants?.FirstOrDefault(t => t.NormalizedName == normalizedName);
}
public TenantConfiguration? Find(Guid id)

7
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs

@ -10,6 +10,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi
{
protected virtual ITenantResolver TenantResolver { get; }
protected virtual ITenantStore TenantStore { get; }
protected virtual ITenantNormalizer TenantNormalizer { get; }
protected virtual ITenantResolveResultAccessor TenantResolveResultAccessor { get; }
protected virtual IStringLocalizer<AbpMultiTenancyResource> StringLocalizer { get; }
@ -17,10 +18,12 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi
ITenantResolver tenantResolver,
ITenantStore tenantStore,
ITenantResolveResultAccessor tenantResolveResultAccessor,
IStringLocalizer<AbpMultiTenancyResource> stringLocalizer)
IStringLocalizer<AbpMultiTenancyResource> stringLocalizer,
ITenantNormalizer tenantNormalizer)
{
TenantResolver = tenantResolver;
TenantStore = tenantStore;
TenantNormalizer = tenantNormalizer;
TenantResolveResultAccessor = tenantResolveResultAccessor;
StringLocalizer = stringLocalizer;
}
@ -69,7 +72,7 @@ public class TenantConfigurationProvider : ITenantConfigurationProvider, ITransi
}
else
{
return await TenantStore.FindAsync(tenantIdOrName);
return await TenantStore.FindAsync(TenantNormalizer.NormalizeName(tenantIdOrName)!);
}
}
}

3
framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_WithDomainResolver_Tests.cs

@ -16,6 +16,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe
{
private readonly Guid _testTenantId = Guid.NewGuid();
private readonly string _testTenantName = "acme";
private readonly string _testTenantNormalizedName = "ACME";
private readonly AbpAspNetCoreMultiTenancyOptions _options;
@ -30,7 +31,7 @@ public class AspNetCoreMultiTenancy_WithDomainResolver_Tests : AspNetCoreMultiTe
{
options.Tenants = new[]
{
new TenantConfiguration(_testTenantId, _testTenantName)
new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName)
};
});

3
framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancy_Without_DomainResolver_Tests.cs

@ -17,6 +17,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul
{
private readonly Guid _testTenantId = Guid.NewGuid();
private readonly string _testTenantName = "acme";
private readonly string _testTenantNormalizedName = "ACME";
private readonly AbpAspNetCoreMultiTenancyOptions _options;
@ -31,7 +32,7 @@ public class AspNetCoreMultiTenancy_Without_DomainResolver_Tests : AspNetCoreMul
{
options.Tenants = new[]
{
new TenantConfiguration(_testTenantId, _testTenantName)
new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName)
};
});

3
framework/test/Volo.Abp.AspNetCore.Serilog.Tests/Volo/Abp/AspNetCore/Serilog/Serilog_Enrichers_Tests.cs

@ -20,6 +20,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase
private readonly Guid _testTenantId = Guid.NewGuid();
private readonly string _testTenantName = "acme";
private readonly string _testTenantNormalizedName = "ACME";
private readonly AbpAspNetCoreMultiTenancyOptions _tenancyOptions;
private readonly AbpAspNetCoreSerilogOptions _serilogOptions;
@ -39,7 +40,7 @@ public class Serilog_Enrichers_Tests : AbpSerilogTestBase
{
options.Tenants = new[]
{
new TenantConfiguration(_testTenantId, _testTenantName)
new TenantConfiguration(_testTenantId, _testTenantName, _testTenantNormalizedName)
};
});
base.ConfigureServices(services);

4
modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor

@ -95,8 +95,8 @@
</Tabs>
</ModalBody>
<ModalFooter>
<Button Color="Color.Primary" Clicked="@(async () => await DeleteAsync(ProviderName,ProviderKey))">@L["ResetToDefault"]</Button>
<Button Color="Color.Secondary" Clicked="CloseModal">@L["Cancel"]</Button>
<Button class="btn btn-link" Clicked="CloseModal">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="@(async () => await DeleteAsync(ProviderName,ProviderKey))">@L["ResetToDefault"]</Button>
<Button Color="Color.Primary" Clicked="SaveAsync">@L["Save"]</Button>
</ModalFooter>
}

4
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor

@ -63,7 +63,7 @@
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@CreateEntityAsync"/>
</ModalFooter>
</Form>
@ -101,7 +101,7 @@
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@UpdateEntityAsync"/>
</ModalFooter>
</Form>

4
modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor

@ -154,7 +154,7 @@
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@CreateEntityAsync" />
</ModalFooter>
</Form>
@ -275,7 +275,7 @@
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@UpdateEntityAsync" />
</ModalFooter>
</Form>

2
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor

@ -81,7 +81,7 @@
}
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseModal">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseModal">@L["Cancel"]</Button>
<Button Color="Color.Primary" Clicked="SaveAsync">@L["Save"]</Button>
</ModalFooter>
</ModalContent>

2
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor

@ -95,7 +95,7 @@
<SubmitButton Clicked="@UpdateSettingsAsync"/>
@if (HasSendTestEmailPermission)
{
<Button style="margin: 0.25rem" Color="Color.Primary" Clicked="OpenSendTestEmailModalAsync">@L["SendTestEmail"]</Button>
<Button style="margin: 0.25rem" Color="Color.Primary" Outline Clicked="OpenSendTestEmailModalAsync">@L["SendTestEmail"]</Button>
}
</Column>

2
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml

@ -31,7 +31,7 @@
</abp-button>
@if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest))
{
<abp-button button-type="Primary" id="SendTestEmailButton">
<abp-button button-type="Outline_Primary" id="SendTestEmailButton">
<i class="fa fa-send"></i> @L["SendTestEmail"]
</abp-button>
}

4
modules/tenant-management/src/Volo.Abp.TenantManagement.Blazor/Pages/TenantManagement/TenantManagement.razor

@ -85,7 +85,7 @@
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@CreateEntityAsync"/>
</ModalFooter>
</Form>
@ -119,7 +119,7 @@
<ExtensionProperties TEntityType="TenantUpdateDto" TResourceType="AbpTenantManagementResource" Entity="@EditingEntity" LH="@LH" ModalType="ExtensionPropertyModalType.EditModal" />
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Outline Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<SubmitButton Clicked="@UpdateEntityAsync"/>
</ModalFooter>
</Form>

4
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantRepository.cs

@ -9,13 +9,13 @@ namespace Volo.Abp.TenantManagement;
public interface ITenantRepository : IBasicRepository<Tenant, Guid>
{
Task<Tenant> FindByNameAsync(
string name,
string normalizedName,
bool includeDetails = true,
CancellationToken cancellationToken = default);
[Obsolete("Use FindByNameAsync method.")]
Tenant FindByName(
string name,
string normalizedName,
bool includeDetails = true
);

12
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/Tenant.cs

@ -10,7 +10,9 @@ namespace Volo.Abp.TenantManagement;
public class Tenant : FullAuditedAggregateRoot<Guid>, IHasEntityVersion
{
public virtual string Name { get; protected set; }
public virtual string NormalizedName { get; protected set; }
public virtual int EntityVersion { get; protected set; }
public virtual List<TenantConnectionString> ConnectionStrings { get; protected set; }
@ -20,10 +22,11 @@ public class Tenant : FullAuditedAggregateRoot<Guid>, IHasEntityVersion
}
protected internal Tenant(Guid id, [NotNull] string name)
protected internal Tenant(Guid id, [NotNull] string name, [CanBeNull] string normalizedName)
: base(id)
{
SetName(name);
SetNormalizedName(normalizedName);
ConnectionStrings = new List<TenantConnectionString>();
}
@ -78,4 +81,9 @@ public class Tenant : FullAuditedAggregateRoot<Guid>, IHasEntityVersion
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength);
}
protected internal virtual void SetNormalizedName([CanBeNull] string normalizedName)
{
NormalizedName = normalizedName;
}
}

8
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantConfigurationCacheItemInvalidator.cs

@ -22,21 +22,21 @@ public class TenantConfigurationCacheItemInvalidator :
public virtual async Task HandleEventAsync(EntityChangedEventData<Tenant> eventData)
{
await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name);
await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName);
}
public virtual async Task HandleEventAsync(EntityDeletedEventData<Tenant> eventData)
{
await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.Name);
await ClearCacheAsync(eventData.Entity.Id, eventData.Entity.NormalizedName);
}
protected virtual async Task ClearCacheAsync(Guid? id, string name)
protected virtual async Task ClearCacheAsync(Guid? id, string normalizedName)
{
await Cache.RemoveManyAsync(
new[]
{
TenantConfigurationCacheItem.CalculateCacheKey(id, null),
TenantConfigurationCacheItem.CalculateCacheKey(null, name),
TenantConfigurationCacheItem.CalculateCacheKey(null, normalizedName),
});
}
}

23
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs

@ -10,20 +10,22 @@ public class TenantManager : DomainService, ITenantManager
{
protected ITenantRepository TenantRepository { get; }
protected IDistributedCache<TenantConfigurationCacheItem> Cache { get; }
protected ITenantNormalizer TenantNormalizer { get; }
public TenantManager(ITenantRepository tenantRepository,
IDistributedCache<TenantConfigurationCacheItem> cache)
public TenantManager(ITenantRepository tenantRepository, IDistributedCache<TenantConfigurationCacheItem> cache, ITenantNormalizer tenantNormalizer)
{
TenantRepository = tenantRepository;
Cache = cache;
TenantNormalizer = tenantNormalizer;
}
public virtual async Task<Tenant> CreateAsync(string name)
{
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name);
return new Tenant(GuidGenerator.Create(), name);
var normalizedName = TenantNormalizer.NormalizeName(name);
await ValidateNameAsync(normalizedName);
return new Tenant(GuidGenerator.Create(), name, normalizedName);
}
public virtual async Task ChangeNameAsync(Tenant tenant, string name)
@ -31,17 +33,20 @@ public class TenantManager : DomainService, ITenantManager
Check.NotNull(tenant, nameof(tenant));
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name, tenant.Id);
await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.Name));
var normalizedName = TenantNormalizer.NormalizeName(name);
await ValidateNameAsync(normalizedName, tenant.Id);
await Cache.RemoveAsync(TenantConfigurationCacheItem.CalculateCacheKey(tenant.NormalizedName));
tenant.SetName(name);
tenant.SetNormalizedName(normalizedName);
}
protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null)
protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null)
{
var tenant = await TenantRepository.FindByNameAsync(name);
var tenant = await TenantRepository.FindByNameAsync(normalizeName);
if (tenant != null && tenant.Id != expectedId)
{
throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", name);
throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", normalizeName);
}
}
}

32
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantStore.cs

@ -27,9 +27,9 @@ public class TenantStore : ITenantStore, ITransientDependency
Cache = cache;
}
public virtual async Task<TenantConfiguration> FindAsync(string name)
public virtual async Task<TenantConfiguration> FindAsync(string normalizedName)
{
return (await GetCacheItemAsync(null, name)).Value;
return (await GetCacheItemAsync(null, normalizedName)).Value;
}
public virtual async Task<TenantConfiguration> FindAsync(Guid id)
@ -38,9 +38,9 @@ public class TenantStore : ITenantStore, ITransientDependency
}
[Obsolete("Use FindAsync method.")]
public virtual TenantConfiguration Find(string name)
public virtual TenantConfiguration Find(string normalizedName)
{
return (GetCacheItem(null, name)).Value;
return (GetCacheItem(null, normalizedName)).Value;
}
[Obsolete("Use FindAsync method.")]
@ -49,9 +49,9 @@ public class TenantStore : ITenantStore, ITransientDependency
return (GetCacheItem(id, null)).Value;
}
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemAsync(Guid? id, string name)
protected virtual async Task<TenantConfigurationCacheItem> GetCacheItemAsync(Guid? id, string normalizedName)
{
var cacheKey = CalculateCacheKey(id, name);
var cacheKey = CalculateCacheKey(id, normalizedName);
var cacheItem = await Cache.GetAsync(cacheKey, considerUow: true);
if (cacheItem != null)
@ -68,16 +68,16 @@ public class TenantStore : ITenantStore, ITransientDependency
}
}
if (!name.IsNullOrWhiteSpace())
if (!normalizedName.IsNullOrWhiteSpace())
{
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{
var tenant = await TenantRepository.FindByNameAsync(name);
var tenant = await TenantRepository.FindByNameAsync(normalizedName);
return await SetCacheAsync(cacheKey, tenant);
}
}
throw new AbpException("Both id and name can't be invalid.");
throw new AbpException("Both id and normalizedName can't be invalid.");
}
protected virtual async Task<TenantConfigurationCacheItem> SetCacheAsync(string cacheKey, [CanBeNull] Tenant tenant)
@ -89,9 +89,9 @@ public class TenantStore : ITenantStore, ITransientDependency
}
[Obsolete("Use GetCacheItemAsync method.")]
protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string name)
protected virtual TenantConfigurationCacheItem GetCacheItem(Guid? id, string normalizedName)
{
var cacheKey = CalculateCacheKey(id, name);
var cacheKey = CalculateCacheKey(id, normalizedName);
var cacheItem = Cache.Get(cacheKey, considerUow: true);
if (cacheItem != null)
@ -108,16 +108,16 @@ public class TenantStore : ITenantStore, ITransientDependency
}
}
if (!name.IsNullOrWhiteSpace())
if (!normalizedName.IsNullOrWhiteSpace())
{
using (CurrentTenant.Change(null)) //TODO: No need this if we can implement to define host side (or tenant-independent) entities!
{
var tenant = TenantRepository.FindByName(name);
var tenant = TenantRepository.FindByName(normalizedName);
return SetCache(cacheKey, tenant);
}
}
throw new AbpException("Both id and name can't be invalid.");
throw new AbpException("Both id and normalizedName can't be invalid.");
}
[Obsolete("Use SetCacheAsync method.")]
@ -129,8 +129,8 @@ public class TenantStore : ITenantStore, ITransientDependency
return cacheItem;
}
protected virtual string CalculateCacheKey(Guid? id, string name)
protected virtual string CalculateCacheKey(Guid? id, string normalizedName)
{
return TenantConfigurationCacheItem.CalculateCacheKey(id, name);
return TenantConfigurationCacheItem.CalculateCacheKey(id, normalizedName);
}
}

2
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs

@ -23,10 +23,12 @@ public static class AbpTenantManagementDbContextModelCreatingExtensions
b.ConfigureByConvention();
b.Property(t => t.Name).IsRequired().HasMaxLength(TenantConsts.MaxNameLength);
b.Property(t => t.NormalizedName).IsRequired().HasMaxLength(TenantConsts.MaxNameLength);
b.HasMany(u => u.ConnectionStrings).WithOne().HasForeignKey(uc => uc.TenantId).IsRequired();
b.HasIndex(u => u.Name);
b.HasIndex(u => u.NormalizedName);
b.ApplyObjectExtensionMappings();
});

8
modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/EfCoreTenantRepository.cs

@ -19,23 +19,23 @@ public class EfCoreTenantRepository : EfCoreRepository<ITenantManagementDbContex
}
public virtual async Task<Tenant> FindByNameAsync(
string name,
string normalizedName,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
.FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken));
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
public virtual Tenant FindByName(string normalizedName, bool includeDetails = true)
{
return DbSet
.IncludeDetails(includeDetails)
.OrderBy(t => t.Id)
.FirstOrDefault(t => t.Name == name);
.FirstOrDefault(t => t.NormalizedName == normalizedName);
}
[Obsolete("Use FindAsync method.")]

8
modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs

@ -20,19 +20,19 @@ public class MongoTenantRepository : MongoDbRepository<ITenantManagementMongoDbC
}
public virtual async Task<Tenant> FindByNameAsync(
string name,
string normalizedName,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.FirstOrDefaultAsync(t => t.Name == name, GetCancellationToken(cancellationToken));
.FirstOrDefaultAsync(t => t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken));
}
[Obsolete("Use FindByNameAsync method.")]
public virtual Tenant FindByName(string name, bool includeDetails = true)
public virtual Tenant FindByName(string normalizedName, bool includeDetails = true)
{
return GetMongoQueryable()
.FirstOrDefault(t => t.Name == name);
.FirstOrDefault(t => t.NormalizedName == normalizedName);
}
[Obsolete("Use FindAsync method.")]

44
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantCacheItemInvalidator_Tests.cs

@ -12,6 +12,7 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement
private readonly ITenantStore _tenantStore;
private readonly ITenantRepository _tenantRepository;
private readonly ITenantManager _tenantManager;
private readonly ITenantNormalizer _tenantNormalizer;
public TenantConfigurationCacheItemInvalidator_Tests()
{
@ -19,86 +20,87 @@ public class TenantConfigurationCacheItemInvalidator_Tests : AbpTenantManagement
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
_tenantManager = GetRequiredService<ITenantManager>();
_tenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
public async Task Get_Tenant_Should_Cached()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
acme.ShouldNotBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull();
await _tenantStore.FindAsync(acme.Id);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.Name);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
await _tenantStore.FindAsync(acme.NormalizedName);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull();
var volosoft = _tenantRepository.FindByName("volosoft");
var volosoft = _tenantRepository.FindByName(_tenantNormalizer.NormalizeName("volosoft"));
volosoft.ShouldNotBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull();
_tenantStore.Find(volosoft.Id);
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
_tenantStore.Find(volosoft.Name);
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
_tenantStore.Find(volosoft.NormalizedName);
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull();
}
[Fact]
public async Task Cache_Should_Invalidator_When_Tenant_Changed()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
acme.ShouldNotBeNull();
// FindAsync will cache tenant.
await _tenantStore.FindAsync(acme.Id);
await _tenantStore.FindAsync(acme.Name);
await _tenantStore.FindAsync(acme.NormalizedName);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldNotBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldNotBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldNotBeNull();
await _tenantRepository.DeleteAsync(acme);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(acme.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.Name))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, acme.NormalizedName))).ShouldBeNull();
var volosoft = await _tenantRepository.FindByNameAsync("volosoft");
var volosoft = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft"));
volosoft.ShouldNotBeNull();
// Find will cache tenant.
_tenantStore.Find(volosoft.Id);
_tenantStore.Find(volosoft.Name);
_tenantStore.Find(volosoft.NormalizedName);
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldNotBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldNotBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldNotBeNull();
await _tenantRepository.DeleteAsync(volosoft);
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(volosoft.Id, null))).ShouldBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.Name))).ShouldBeNull();
(_cache.Get(TenantConfigurationCacheItem.CalculateCacheKey(null, volosoft.NormalizedName))).ShouldBeNull();
var abp = await _tenantRepository.FindByNameAsync("abp");
var abp = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("abp"));
abp.ShouldNotBeNull();
// Find will cache tenant.
await _tenantStore.FindAsync(abp.Id);
await _tenantStore.FindAsync(abp.Name);
await _tenantStore.FindAsync(abp.NormalizedName);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldNotBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.Name))).ShouldNotBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, abp.NormalizedName))).ShouldNotBeNull();
await _tenantManager.ChangeNameAsync(abp, "abp2");
await _tenantRepository.UpdateAsync(abp);
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(abp.Id, null))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp"))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, "abp2"))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp")))).ShouldBeNull();
(await _cache.GetAsync(TenantConfigurationCacheItem.CalculateCacheKey(null, _tenantNormalizer.NormalizeName("abp2")))).ShouldBeNull();
}
}

11
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs

@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Xunit;
namespace Volo.Abp.TenantManagement;
@ -8,19 +9,21 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase
{
private readonly ITenantManager _tenantManager;
private readonly ITenantRepository _tenantRepository;
private readonly ITenantNormalizer _tenantNormalizer;
public TenantManager_Tests()
{
_tenantManager = GetRequiredService<ITenantManager>();
_tenantRepository = GetRequiredService<ITenantRepository>();
_tenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
public async Task CreateAsync()
{
var tenant = await _tenantManager.CreateAsync("Test");
tenant.Name.ShouldBe("Test");
tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("Test"));
}
[Fact]
@ -32,18 +35,20 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase
[Fact]
public async Task ChangeNameAsync()
{
var tenant = await _tenantRepository.FindByNameAsync("volosoft");
var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("volosoft"));
tenant.ShouldNotBeNull();
tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("volosoft"));
await _tenantManager.ChangeNameAsync(tenant, "newVolosoft");
tenant.Name.ShouldBe("newVolosoft");
tenant.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("newVolosoft"));
}
[Fact]
public async Task ChangeName_Tenant_Name_Can_Not_Duplicate()
{
var tenant = await _tenantRepository.FindByNameAsync("acme");
var tenant = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
tenant.ShouldNotBeNull();
await Assert.ThrowsAsync<BusinessException>(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft"));

7
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs

@ -9,25 +9,28 @@ public class TenantStore_Tests : AbpTenantManagementDomainTestBase
{
private readonly ITenantStore _tenantStore;
private readonly ITenantRepository _tenantRepository;
private readonly ITenantNormalizer _tenantNormalizer;
public TenantStore_Tests()
{
_tenantStore = GetRequiredService<ITenantStore>();
_tenantRepository = GetRequiredService<ITenantRepository>();
_tenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
public async Task FindAsyncByName()
{
var acme = await _tenantStore.FindAsync("acme");
var acme = await _tenantStore.FindAsync(_tenantNormalizer.NormalizeName("acme")!);
acme.ShouldNotBeNull();
acme.Name.ShouldBe("acme");
acme.NormalizedName.ShouldBe(_tenantNormalizer.NormalizeName("acme")!);
}
[Fact]
public async Task FindAsyncById()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
acme.ShouldNotBeNull();
(await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull();

7
modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs

@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Xunit;
namespace Volo.Abp.TenantManagement;
@ -7,16 +8,18 @@ namespace Volo.Abp.TenantManagement;
public class Tenant_Tests : AbpTenantManagementDomainTestBase
{
private readonly ITenantRepository _tenantRepository;
private readonly ITenantNormalizer _tenantNormalizer;
public Tenant_Tests()
{
_tenantRepository = GetRequiredService<ITenantRepository>();
_tenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
public async Task FindDefaultConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
acme.ShouldNotBeNull();
acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value");
@ -25,7 +28,7 @@ public class Tenant_Tests : AbpTenantManagementDomainTestBase
[Fact]
public async Task FindConnectionString()
{
var acme = await _tenantRepository.FindByNameAsync("acme");
var acme = await _tenantRepository.FindByNameAsync(_tenantNormalizer.NormalizeName("acme"));
acme.ShouldNotBeNull();
acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value");

5
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/LazyLoad_Tests.cs

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Xunit;
@ -11,10 +12,12 @@ public abstract class LazyLoad_Tests<TStartupModule> : TenantManagementTestBase<
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
public ITenantNormalizer TenantNormalizer { get; }
protected LazyLoad_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
TenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
@ -22,7 +25,7 @@ public abstract class LazyLoad_Tests<TStartupModule> : TenantManagementTestBase<
{
using (var uow = GetRequiredService<IUnitOfWorkManager>().Begin())
{
var role = await TenantRepository.FindByNameAsync("acme", includeDetails: false);
var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: false);
role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue();

17
modules/tenant-management/test/Volo.Abp.TenantManagement.TestBase/Volo/Abp/TenantManagement/TenantRepository_Tests.cs

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Xunit;
namespace Volo.Abp.TenantManagement;
@ -11,22 +12,24 @@ public abstract class TenantRepository_Tests<TStartupModule> : TenantManagementT
where TStartupModule : IAbpModule
{
public ITenantRepository TenantRepository { get; }
public ITenantNormalizer TenantNormalizer { get; }
protected TenantRepository_Tests()
{
TenantRepository = GetRequiredService<ITenantRepository>();
TenantNormalizer = GetRequiredService<ITenantNormalizer>();
}
[Fact]
public async Task FindByNameAsync()
{
var tenant = await TenantRepository.FindByNameAsync("acme");
var tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"));
tenant.ShouldNotBeNull();
tenant = await TenantRepository.FindByNameAsync("undefined-tenant");
tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("undefined-tenant"));
tenant.ShouldBeNull();
tenant = await TenantRepository.FindByNameAsync("acme", includeDetails: true);
tenant = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"), includeDetails: true);
tenant.ShouldNotBeNull();
tenant.ConnectionStrings.Count.ShouldBeGreaterThanOrEqualTo(2);
}
@ -34,7 +37,7 @@ public abstract class TenantRepository_Tests<TStartupModule> : TenantManagementT
[Fact]
public async Task FindAsync()
{
var tenantId = (await TenantRepository.FindByNameAsync("acme")).Id;
var tenantId = (await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"))).Id;
var tenant = await TenantRepository.FindAsync(tenantId);
tenant.ShouldNotBeNull();
@ -51,14 +54,14 @@ public abstract class TenantRepository_Tests<TStartupModule> : TenantManagementT
public async Task GetListAsync()
{
var tenants = await TenantRepository.GetListAsync();
tenants.ShouldContain(t => t.Name == "acme");
tenants.ShouldContain(t => t.Name == "volosoft");
tenants.ShouldContain(t => t.Name == "acme" && t.NormalizedName == TenantNormalizer.NormalizeName("acme"));
tenants.ShouldContain(t => t.Name == "volosoft" && t.NormalizedName == TenantNormalizer.NormalizeName("volosoft"));
}
[Fact]
public async Task Should_Eager_Load_Tenant_Collections()
{
var role = await TenantRepository.FindByNameAsync("acme");
var role = await TenantRepository.FindByNameAsync(TenantNormalizer.NormalizeName("acme"));
role.ConnectionStrings.ShouldNotBeNull();
role.ConnectionStrings.Any().ShouldBeTrue();
}

9
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240108044306_Initial")]
[Migration("20240125061235_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1687,10 +1687,17 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -913,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -1684,10 +1684,17 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240108044315_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240108044315_Initial")]
[Migration("20240125061501_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1687,10 +1687,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240108044243_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -913,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -1684,10 +1684,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240108044236_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Host.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240108044236_Initial")]
[Migration("20240125061101_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1687,10 +1687,17 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240108044236_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -913,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -1684,10 +1684,17 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240108044233_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Mvc.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240108044233_Initial")]
[Migration("20240125061143_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1687,10 +1687,17 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240108044233_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20240125061143_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -913,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -1684,10 +1684,17 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240108044016_Initial.Designer.cs → templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240108044016_Initial")]
[Migration("20240125061248_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1739,10 +1739,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240108044016_Initial.cs → templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs

@ -317,6 +317,7 @@ namespace MyCompanyName.MyProjectName.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -939,6 +940,11 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -1736,10 +1736,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240108044243_Initial.Designer.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(AuthServerDbContext))]
[Migration("20240108044243_Initial")]
[Migration("20240125061344_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1687,10 +1687,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240108044315_Initial.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20240125061344_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -913,6 +914,11 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs

@ -1684,10 +1684,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

9
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240108044309_Initial.Designer.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
[Migration("20240108044309_Initial")]
[Migration("20240125061321_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1328,10 +1328,17 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240108044309_Initial.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20240125061321_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -777,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs

@ -1325,10 +1325,17 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

31
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.Designer.cs

@ -0,0 +1,31 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyCompanyName.MyProjectName.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))]
[Migration("20240125061400_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
#pragma warning restore 612, 618
}
}
}

22
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20240125061400_Initial.cs

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MyCompanyName.MyProjectName.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

28
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs

@ -0,0 +1,28 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyCompanyName.MyProjectName.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))]
partial class MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
#pragma warning restore 612, 618
}
}
}

9
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240108044305_Initial.Designer.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations
{
[DbContext(typeof(UnifiedDbContext))]
[Migration("20240108044305_Initial")]
[Migration("20240125061424_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1328,10 +1328,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

6
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240108044305_Initial.cs → templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20240125061424_Initial.cs

@ -296,6 +296,7 @@ namespace MyCompanyName.MyProjectName.Migrations
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NormalizedName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
@ -777,6 +778,11 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpTenants",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_AbpTenants_NormalizedName",
table: "AbpTenants",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AbpUserClaims_UserId",
table: "AbpUserClaims",

7
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

@ -1325,10 +1325,17 @@ namespace MyCompanyName.MyProjectName.Migrations
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.HasKey("Id");
b.HasIndex("Name");
b.HasIndex("NormalizedName");
b.ToTable("AbpTenants", (string)null);
});

Loading…
Cancel
Save