Browse Source

Merge pull request #1 from abpframework/dev

update last repo
pull/10474/head
TotPeRo 5 years ago
committed by GitHub
parent
commit
233d10b35b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      .github/workflows/auto-pr.yml
  2. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/sk.json
  3. 282
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json
  4. 37
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json
  5. 6
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  6. 296
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json
  7. 147
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json
  8. 202
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json
  9. 1
      build/common.ps1
  10. 2
      common.props
  11. 3
      docs/en/Best-Practices/Domain-Services.md
  12. 3
      docs/en/Best-Practices/Index.md
  13. 174
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/POST.md
  14. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/abp-44-cover.png
  15. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/ddd-book.png
  16. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/dotnetfoundation-sponsor-volosoft.png
  17. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/elsa-overview.gif
  18. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/leptonx.png
  19. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-admin.png
  20. BIN
      docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-public.png
  21. 52
      docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/POST.md
  22. BIN
      docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/overall-solution.png
  23. 8
      docs/en/CLI-New-Command-Samples.md
  24. 8
      docs/en/CLI.md
  25. 4
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md
  26. BIN
      docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png
  27. 2
      docs/en/Connection-Strings.md
  28. 6
      docs/en/Customizing-Application-Modules-Extending-Entities.md
  29. 53
      docs/en/Distributed-Event-Bus.md
  30. 834
      docs/en/Entity-Framework-Core-Migrations.md
  31. 6
      docs/en/Entity-Framework-Core-MySQL.md
  32. 14
      docs/en/Entity-Framework-Core-Oracle-Devart.md
  33. 12
      docs/en/Entity-Framework-Core-Oracle-Official.md
  34. 26
      docs/en/Entity-Framework-Core-Other-DBMS.md
  35. 6
      docs/en/Entity-Framework-Core-PostgreSQL.md
  36. 6
      docs/en/Entity-Framework-Core-SQLite.md
  37. 2
      docs/en/Global-Features.md
  38. 48
      docs/en/Local-Event-Bus.md
  39. 8
      docs/en/Modules/Docs.md
  40. 4
      docs/en/Repositories.md
  41. 14
      docs/en/Road-Map.md
  42. 18
      docs/en/Startup-Templates/Application.md
  43. 28
      docs/en/Tutorials/Part-1.md
  44. 6
      docs/en/Tutorials/Part-10.md
  45. 4
      docs/en/Tutorials/Part-4.md
  46. 6
      docs/en/Tutorials/Part-7.md
  47. 16
      docs/en/Tutorials/Todo/Index.md
  48. BIN
      docs/en/Tutorials/Todo/todo-efcore-migration.png
  49. BIN
      docs/en/Tutorials/images/bookstore-efcore-migration-authors.png
  50. BIN
      docs/en/Tutorials/images/bookstore-efcore-migration.png
  51. 2
      docs/en/UI/AspNetCore/Theming.md
  52. 2
      docs/en/Upgrading.md
  53. 139
      docs/en/docs-nav.json
  54. BIN
      docs/en/images/bookstore-visual-studio-solution-v3.png
  55. BIN
      docs/en/images/docs-module_solution-explorer.png
  56. 466
      docs/pt-BR/MongoDB.md
  57. 6
      docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md
  58. 55
      docs/zh-Hans/Distributed-Event-Bus.md
  59. 283
      docs/zh-Hans/Entity-Framework-Core.md
  60. 48
      docs/zh-Hans/Local-Event-Bus.md
  61. 2
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo.Abp.AspNetCore.Components.Server.csproj
  62. 6
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs
  63. 29
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs
  64. 9
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs
  65. 13
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs
  66. 32
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs
  67. 14
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  68. 23
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs
  69. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs
  70. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sk.json
  71. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs
  72. 26
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs
  73. 3
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs
  74. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs
  75. 33
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs
  76. 19
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs
  77. 9
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs
  78. 21
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs
  79. 10
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/sk.json
  80. 8
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  81. 14
      framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor
  82. 27
      framework/src/Volo.Abp.BlazoriseUI/Components/RadarSpinner.razor
  83. 8
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
  84. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs
  85. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProxyCommandBase.cs
  86. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/RemoveProxyCommand.cs
  87. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs
  88. 26
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs
  89. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
  90. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  91. 2
      framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs
  92. 11
      framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs
  93. 6
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/sk.json
  94. 31
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorListExtensions.cs
  95. 25
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/sk.json
  96. 25
      framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json
  97. 8
      framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/sk.json
  98. 6
      framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/sk.json
  99. 17
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  100. 5
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs

16
.github/workflows/auto-pr.yml

@ -1,10 +1,10 @@
name: Merge branch dev with rel-4.3
name: Merge branch dev with rel-4.4
on:
push:
branches:
- rel-4.3
- rel-4.4
jobs:
merge-dev-with-rel-4-3:
merge-dev-with-rel-4-4:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -12,13 +12,13 @@ jobs:
ref: dev
- name: Reset promotion branch
run: |
git fetch origin rel-4.3:rel-4.3
git reset --hard rel-4.3
git fetch origin rel-4.4:rel-4.4
git reset --hard rel-4.4
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
branch: auto-merge/rel-4-3/${{github.run_number}}
title: Merge branch dev with rel-4.3
body: This PR generated automatically to merge dev with rel-4.3. Please review the changed files before merging to prevent any errors that may occur.
branch: auto-merge/rel-4-4/${{github.run_number}}
title: Merge branch dev with rel-4.4
body: This PR generated automatically to merge dev with rel-4.4. Please review the changed files before merging to prevent any errors that may occur.
reviewers: ${{github.actor}}
token: ${{ github.token }}

14
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/sk.json

@ -0,0 +1,14 @@
{
"culture": "sk",
"texts": {
"Account": "Účet ABP - Prihlásenie a registrácia | ABP.IO",
"Welcome": "Vitajte",
"UseOneOfTheFollowingLinksToContinue": "Ak chcete pokračovať, použite jeden z nasledujúcich odkazov",
"FrameworkHomePage": "Domovská stránka frameworku",
"FrameworkDocumentation": "Dokumentácia k frameworku",
"OfficialBlog": "Oficiálny blog",
"CommercialHomePage": "Komerčná domovská stránka",
"CommercialSupportWebSite": "Webová stránka komerčnej podpory",
"CommunityWebSite": "Webová stránka ABP komunity"
}
}

282
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json

@ -0,0 +1,282 @@
{
"culture": "sk",
"texts": {
"Permission:Organizations": "Organizácie",
"Permission:Manage": "Správa organizácií",
"Permission:DiscountRequests": "Žiadosti o zľavu",
"Permission:DiscountManage": "Správa žiadostí o zľavu",
"Permission:Disable": "Zakázať",
"Permission:Enable": "Povoliť",
"Permission:EnableSendEmail": "Povoliť odosielanie emailov",
"Permission:SendEmail": "Odoslať e-mail",
"Permission:NpmPackages": "Balíky NPM",
"Permission:NugetPackages": "Balíky Nuget",
"Permission:Maintenance": "Údržba",
"Permission:Maintain": "Spustiť údržbu",
"Permission:ClearCaches": "Vymazať vyrovnávaciu pamäť",
"Permission:Modules": "Moduly",
"Permission:Packages": "Balíky",
"Permission:Edit": "Upraviť",
"Permission:Delete": "Zmazať",
"Permission:Create": "Vytvoriť",
"Permission:Accounting": "Účtovníctvo",
"Permission:Accounting:Quotation": "Ponuka",
"Permission:Accounting:Invoice": "Faktúra",
"Menu:Organizations": "Organizácie",
"Menu:Accounting": "Účtovníctvo",
"Menu:Packages": "Balíky",
"Menu:DiscountRequests": "Žiadosti o zľavu",
"NpmPackageDeletionWarningMessage": "Tento balík NPM bude zmazaný. Chcete operáciu potvrdiť?",
"NugetPackageDeletionWarningMessage": "Tento balík Nuget bude zmazaný. Chcete operáciu potvrdiť?",
"ModuleDeletionWarningMessage": "Tento modul bude zmazaný. Chcete operáciu potvrdiť?",
"Name": "Názov",
"DisplayName": "Zobrazený názov",
"ShortDescription": "Krátky popis",
"NameFilter": "Názov",
"CreationTime": "Čas vytvorenia",
"IsPro": "Je pro",
"IsFreeToActiveLicenseOwners": "Zadarmo pre majiteľov licencií",
"ShowOnModuleList": "Zobraziť v zozname modulov",
"EfCoreConfigureMethodName": "Konfigurovať názov metódy",
"IsProFilter": "Je pro",
"ApplicationType": "Typ aplikácie",
"Target": "Cieľ",
"TargetFilter": "Cieľ",
"ModuleClass": "Trieda modulu",
"NugetPackageTarget.DomainShared": "Domain Shared",
"NugetPackageTarget.Domain": "Domain",
"NugetPackageTarget.Application": "Application",
"NugetPackageTarget.ApplicationContracts": "Application Contracts",
"NugetPackageTarget.HttpApi": "Http Api",
"NugetPackageTarget.HttpApiClient": "Http Api Client",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "Upraviť",
"Delete": "Zmazať",
"Refresh": "Obnoviť",
"NpmPackages": "Balíky NPM",
"NugetPackages": "Balíky Nuget",
"NpmPackageCount": "Počet NPM balíkov ",
"NugetPackageCount": "Počet Nuget balíkov",
"Module": "Moduly",
"ModuleInfo": "Informácie o module",
"CreateANpmPackage": "Vytvoriť NPM balík",
"CreateAModule": "Vytvoriť modul",
"CreateANugetPackage": "Vytvoriť Nuget balík",
"AddNew": "Pridať nový",
"PackageAlreadyExist{0}": "Balík \"{0}\" je už pridaný.",
"ModuleAlreadyExist{0}": "Modul \"{0}\" je už pridaný.",
"ClearCache": "Vyčistiť vyrovnávaciu pamäť",
"SuccessfullyCleared": "Úspešne vyčistené",
"Menu:NpmPackages": "NPM balíky",
"Menu:Modules": "Moduly",
"Menu:Maintenance": "Údržba",
"Menu:NugetPackages": "Nuget balíky",
"CreateAnOrganization": "Vytvoriť organizáciu",
"Organizations": "Organizácie",
"LongName": "Dlhý názov",
"LicenseType": "Typ licencie",
"MissingLicenseTypeField": "Pole Typ licencie je povinné!",
"LicenseStartTime": "Čas začiatku platnosti licencie",
"LicenseEndTime": "Čas ukončenia platnosti licencie",
"AllowedDeveloperCount": "Povolený počet vývojárov",
"UserNameOrEmailAddress": "Používateľské meno alebo e-mailová adresa",
"AddOwner": "Pridať vlastníka",
"UserName": "Používateľské meno",
"Email": "Email",
"Developers": "Vývojári",
"AddDeveloper": "Pridať vývojára",
"Create": "Vytvoriť",
"UserNotFound": "Používateľ nebol nájdený",
"{0}WillBeRemovedFromDevelopers": "{0} bude odstranený z vývojárov, chcete akciu potvrdiť?",
"{0}WillBeRemovedFromOwners": "{0} bude odstranený z vlastníkov, chcete akciu potvrdiť?",
"{0}WillBeRemovedFromMembers": "{0} bude odstranený z členov, chcete akciu potvrdiť?",
"Computers": "Počítače",
"UniqueComputerId": "Jedinečný identifikátor počítača",
"LastSeenDate": "Dátum posledného zobrazenia",
"{0}Computer{1}WillBeRemovedFromRecords": "Počítač používateľa {0} ({1}) bude zo záznamov odstránený",
"OrganizationDeletionWarningMessage": "Organizácia bude vymazaná",
"DeletingLastOwnerWarningMessage": "Organizácia musí mať aspoň jedného vlastníka! Z tohto dôvodu nie je možné vlastníka odstrániť",
"This{0}AlreadyExistInThisOrganization": "Tento {0} už v tejto organizácii existuje",
"AreYouSureYouWantToDeleteAllComputers": "Ste si istí, že chcete zmazať všetky počítače?",
"DeleteAll": "Zmazať všetko",
"DoYouWantToCreateNewUser": "Chcete vytvoriť nového používateľa?",
"MasterModules": "Hlavné moduly",
"OrganizationName": "Názov organizácie",
"CreationDate": "Dátum vytvorenia",
"LicenseStartDate": "Dátum začiatku platnosti licencie",
"LicenseEndDate": "Dátum ukončenia platnosti licencie",
"OrganizationNamePlaceholder": "Názov organizácie...",
"TotalQuestionCountPlaceholder": "Celkový počet otázok...",
"RemainingQuestionCountPlaceholder": "Počet zostávajúcich otázok...",
"LicenseTypePlaceholder": "Typ licencie...",
"CreationDatePlaceholder": "Dátum vytvorenia...",
"LicenseStartDatePlaceholder": "Dátum začiatku platnosti licencie...",
"LicenseEndDatePlaceholder": "Dátum ukončenia platnosti licencie...",
"UsernameOrEmail": "Používateľské meno alebo email",
"UsernameOrEmailPlaceholder": "Používateľské meno alebo email...",
"Member": "Člen",
"PurchaseOrderNo": "Nákupná objednávka č.",
"QuotationDate": "Dátum cenovej ponuky",
"CompanyName": "Názov spoločnosti",
"CompanyAddress": "Adresa spoločnosti",
"Price": "Cena",
"DiscountText": "Text zľavy",
"DiscountQuantity": "Zľavnené množstvo",
"DiscountPrice": "Zľavová cena",
"Quotation": "Ponuka",
"ExtraText": "Extra text",
"ExtraAmount": "Dodatočná suma",
"DownloadQuotation": "Stiahnuť ponuku",
"Invoice": "Faktúra",
"TaxNumber": "DIČ",
"InvoiceNumber": "Číslo faktúry",
"InvoiceDate": "Dátum faktúry",
"InvoiceNote": "Poznámka k faktúre",
"Quantity": "Množstvo",
"AddProduct": "Pridať produkt",
"AddProductWarning": "Musíte pridať produkt!",
"TotalPrice": "Celková cena",
"Generate": "Generovať",
"MissingQuantityField": "Pole Množstvo je povinné!",
"MissingPriceField": "Pole Cena je povinné!",
"CodeUsageStatus": "Stav",
"Country": "Krajina",
"DeveloperCount": "Počet vývojárov",
"RequestCode": "Kód žiadosti",
"WebSite": "Internetová stránka",
"GithubUsername": "Github používateľské meno",
"PhoneNumber": "Telefónne číslo",
"ProjectDescription": "Popis projektu",
"Referrer": "Sprostredkovateľ",
"DiscountRequests": "Žiadosť o zľavu",
"Copylink": "Kopírovať odkaz",
"Disable": "Zakázať",
"Enable": "Povoliť",
"EnableSendEmail": "Povoliť odoslanie e-mailu",
"SendEmail": "Odošli e-mail",
"SuccessfullyDisabled": "Úspešne zakázané",
"SuccessfullyEnabled": "Úspešne povolené",
"EmailSent": "Email bol odoslaný",
"SuccessfullySent": "Úspešne odoslané",
"SuccessfullyDeleted": "Úspešne zmazané",
"DiscountRequestDeletionWarningMessage": "Žiadosť o zľavu bude vymazaná",
"BusinessType": "Typ podnikania",
"TotalQuestionCount": "Celkový počet otázok",
"RemainingQuestionCount": "Zostávajúci počet otázok",
"TotalQuestionMustBeGreaterWarningMessage": "Celkový počet otázok musí byť väčší ako zostávajúci počet otázok !",
"QuestionCountsMustBeGreaterThanZero": "Celkový počet otázok a zostávajúci počet otázok sa musí rovnať alebo byť väčší ako nula!",
"UnlimitedQuestionCount": "Neobmedzený počet otázok",
"Notes": "Poznámky",
"Menu:Community": "Komunita",
"Menu:Articles": "Články",
"Wait": "Čakať",
"Approve": "Schváliť",
"Reject": "Zamietnuť",
"Details": "Podrobnosti",
"Url": "Url",
"Title": "Nadpis",
"ContentSource": "Zdroj obsahu",
"Status": "Stav",
"ReadArticle": "Prečítať článok",
"ArticleHasBeenWaiting": "Článok čakal",
"ArticleHasBeenApproved": "Článok bol schválený",
"ArticleHasBeenRejected": "Článok bol zamietnutý",
"Permission:Community": "Komunita",
"Permission:CommunityArticle": "Článok",
"Link": "Odkaz",
"Enum:ContentSource:0": "Github",
"Enum:ContentSource:1": "Externý",
"Enum:Status:0": "Čaká",
"Enum:Status:1": "Zamietný",
"Enum:Status:2": "Schválený",
"Summary": "Zhrnutie",
"AuthorName": "Meno autora",
"CoverImage": "Titulný obrázok",
"RemoveCacheConfirmationMessage": "Naozaj chcete odstrániť vyrovnávaciu pamäť pre článok \"{0}\"?",
"SuccessfullyRemoved": "Úspešne vyčistené",
"RemoveCache": "Odstrániť vyrovnávaciu pamäť",
"Language": "Jazyk",
"Optional": "Voliteľné",
"CreateArticleLanguageInfo": "Jazyk, v ktorom je príspevok napísaný",
"Enum:ContentSource:2": "Video príspevok",
"VideoPreview": "Náhľad videa",
"VideoPreviewErrorMessage": "Poskytnutú url videa sa z Youtube nepodarilo načítať. Video môže byť súkromné alebo adresa URL nie je dostupná.",
"DeleteCoverImage": "Odstránenie titulného obrázku",
"DeleteCoverImageConfirmationMessage": "Ste si istý, že chcete zmazať titulný obrázok pre \"{0}\"?",
"DeleteCoverImageSuccessMessage": "Titulný obrázok úspešne zmazaný",
"PaymentsOf": "Platby",
"ShowPaymentsOfOrganization": "Platby",
"Date": "Dátum",
"Products": "Produkty",
"TotalAmount": "Celková suma",
"Currency": "Mena",
"Gateway": "Brána",
"State": "Štát",
"FailReason": "Dôvod zlyhania",
"ReIndexAllPosts": "Reindexovanie všetkých príspevkov",
"ReIndexAllPostsConfirmationMessage": "Ste si istý, že chcete reindexovať všetky príspevky?",
"SuccessfullyReIndexAllPosts": "Všetky príspevky boli úspešne reindexované.",
"Permission:FullSearch": "Vyhľadávanie v celom texte",
"Menu:CliAnalytics": "Cli analytiky",
"TemplateName": "Názov šablóny",
"TemplateVersion": "Verzia šablóny",
"DatabaseProvider": "Poskytovateľ databázy",
"IsTiered": "Je viacúrovňový",
"ProjectName": "Názov projektu",
"Username": "Meno používateľa",
"Tool": "Nástroj",
"Command": "Príkaz",
"UiFramework": "UI frameworku",
"Options": "Možnosti",
"CliAnalytics": "Cli analytiky",
"Permission:CliAnalyticses": "Cli analytiky",
"Permission:CliAnalytics": "Cli analytiky",
"Search": "Hľadať",
"ClearFilter": "Vyčistiť filter",
"LicensePrivateKey": "Privátny kľúč licencie",
"LicensePublicKey": "Verejný kľúč licencie",
"ApiKey": "NuGet API kľúč ",
"ShowInvoiceRequestsOfOrganization": "Žiadosti o faktúru",
"ShowQuestionsOfOrganization": "Otázky",
"Question": "Otázka",
"Open": "Otvoriť",
"Questions": "Otázky",
"InvoiceRequests": "Žiadosti o faktúru",
"Address": "Adresa",
"TaxNo": "DIČ",
"Permission:InvoiceRequest": "Žiadosť o faktúru",
"Permission:Question": "Otázka",
"AddNoteSuccessMessage": "Poznámka úspešne pridaná",
"NameSurname": "Meno Priezvisko",
"Note": "Poznámka",
"Add": "Pridať",
"ProjectDownloads": "Stiahnutia projektu",
"ShowProjectDownloadsOfOrganization": "Stiahnutia projektu",
"ShowAuditLogsOfOrganization": "Audit logy",
"Enum:EntityChangeType:0": "Vytvorené",
"Enum:EntityChangeType:1": "Aktualizované",
"Enum:EntityChangeType:2": "Zmazané",
"TenantId": "ID tenanta",
"ChangeTime": "Čas zmeny",
"EntityTypeFullName": "Úplný názov typu entity",
"AuditLogsFor{0}Organization": "Audit logy pre organizáciu \"{0}\"",
"Permission:EntityChange": "Zmena entity",
"Permission:ProjectDownload": "Stiahnutie projektu",
"Permission:PaymentRequest": "Žiadosť o platbu",
"CreatorEmailAddress": "Emailová adresa autora",
"EmailSendDate": "Dátum odoslania emailu",
"PaymentRequestsFor{0}Organization": "Žiadosti o platbu pre organizáciu \"{0}\"",
"PaymentDetails": "Podrobnosti o platbe",
"PaymentProduct": "Platobný produkt",
"ProductName": "Názov produktu",
"Code": "Kód",
"GenerateInvoice": "Generovať faktúru",
"ExportOrganizationsToExcel": "Export do Excelu",
"ThisExtensionIsNotAllowed": "Táto prípona nie je povolená.",
"TheFileIsTooLarge": "Súbor je príliš veľký!",
"ArticleDeletionConfirmationMessage": "Ste si istí, že chcete tento článok úplne vymazať?",
"ChooseCoverImage": "Vybrať titulný obrázok..."
}
}

37
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json

@ -0,0 +1,37 @@
{
"culture": "sk",
"texts": {
"Volo.AbpIo.Domain:010004": "Dosiahnutý maximálny počet členov!",
"Volo.AbpIo.Domain:010005": "Dosiahnutý maximálny počet majiteľov!",
"Volo.AbpIo.Domain:010006": "Tento používateľ je už vlastníkom v tejto organizácii!",
"Volo.AbpIo.Domain:010007": "Tento používateľ je už vývojárom v tejto organizácii!",
"Volo.AbpIo.Domain:010008": "Povolený počet vývojárov nemôže byť menší ako aktuálny počet vývojárov!",
"Volo.AbpIo.Domain:010009": "Povolený počet vývojárov nemôže byť menší ako 0!",
"Volo.AbpIo.Domain:010010": "Maximálny počet mac adries je prekročený!",
"Volo.AbpIo.Domain:010011": "Osobná licencia nemôže mať viac ako 1 vývojára!",
"Volo.AbpIo.Domain:010012": "Licenciu nie je možné predĺžiť mesiac po jej vypršaní!",
"Volo.AbpIo.Domain:020001": "NPM balík sa nepodarilo zmazať, pretože Nuget balíky \"{NugetPackages}\" sú závislé na tomto balíku.",
"Volo.AbpIo.Domain:020002": "NPM balík sa nepodarilo zmazať, pretože tento balík používajú moduly \"{Modules}\".",
"Volo.AbpIo.Domain:020003": "NPM balík sa nepodarilo zmazať, pretože tento balík používajú moduly \"{Modules}\" a Nuget balíky \"{NugetPackages}\" sú závislé na tomto balíku.",
"Volo.AbpIo.Domain:020004": "Nuget balík sa nepodarilo zmazať, pretože tento balík používajú moduly \"{Modules}\".",
"WantToLearn?": "Chcete sa učiť?",
"ReadyToGetStarted?": "Ste pripravený začať?",
"JoinOurCommunity": "Pripojte sa k našej komunite",
"GetStartedUpper": "ZAČAŤ",
"ForkMeOnGitHub": "Fork me on GitHub",
"Features": "Funkcie",
"GetStarted": "Začať",
"Documents": "Dokumenty",
"Community": "Komunita",
"ContributionGuide": "Sprievodca prispievaním",
"Blog": "Blog",
"Commercial": "Commercial",
"MyAccount": "Moje konto",
"Permission:License": "Licencia",
"Permission:UserInfo": "Informácie o používateľovi",
"SeeDocuments": "Pozrieť dokumenty",
"Samples": "Ukážky",
"Framework": "Framework",
"Support": "Podpora"
}
}

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

@ -196,14 +196,14 @@
"WhatHappensWhenLicenseEndsExplanation4": "You can not install new modules and themes added to the ABP Commercial platform after your license ends.",
"WhatHappensWhenLicenseEndsExplanation5": "You can not use the ABP Suite.",
"WhatHappensWhenLicenseEndsExplanation6": "You can not get the <a href=\"{0}\">premium support</a> anymore.",
"WhatHappensWhenLicenseEndsExplanation7": "You can renew your subscription if you want to continue to get these benefits. There is a 20% discount when you renew your subscription.",
"WhatHappensWhenLicenseEndsExplanation7": "You can renew your subscription if you want to continue to get these benefits. If you renew your subscription within 1 month after your license expires, a 20% discount is applied.",
"WhenShouldIRenewMyLicense": "When should I renew my license?",
"WhenShouldIRenewMyLicenseExplanation1": "If you renew your license within <strong>1 month</strong> after your license expires, %20 discount will be applied to total license price.",
"WhenShouldIRenewMyLicenseExplanation1": "If you renew your license within <strong>1 month</strong> after your license expires, a %20 discount is be applied.",
"WhenShouldIRenewMyLicenseExplanation2": "If you renew your license after 1 month from your license expire date, the renew price will be same as license purchase price and there will be no discount for your renewal.",
"TrialPlan": "Do you have a trial plan?",
"TrialPlanExplanation": "For now, ABP Commercial doesn't have a trial plan. For the Team licenses we provide 30 days money back guarantee. You can just request a refund in the first 30 days. For the Business and Enterprise licenses, we provide 60% refund in 30 days. This is because Business and Enterprise licenses include the full source code of all the modules and the themes.",
"DoYouAcceptBankWireTransfer": "Do you accept bank wire transfer?",
"DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfer.<br />After sending the license amount via bank wire transfer, send us your receipt and the requested license type via e-mail.<br />Our international bank account information:",
"DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfer.<br />After sending the license fee via bank transfer, email us at info@abp.io your receipt and the type of license requested. Our international bank account information:",
"HowToUpgrade": "How to upgrade existing applications when a new version is available?",
"HowToUpgradeExplanation1": "When you create a new application using ABP Commercial, all the modules and the theme are used as NuGet and NPM packages. So, you can easily upgrade the packages when a new version is available.",
"HowToUpgradeExplanation2": "In addition to the standard NuGet/NPM upgrades, <a href=\"{0}\">ABP CLI</a> provides an update command that automatically finds and upgrades all ABP related packages in your solution.",

296
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json

@ -0,0 +1,296 @@
{
"culture": "sk",
"texts": {
"OrganizationManagement": "Správa organizácii",
"OrganizationList": "Zoznam organizácií",
"Volo.AbpIo.Commercial:010003": "Nie ste vlastníkom tejto organizácie!",
"OrganizationNotFoundMessage": "Nenašla sa žiadna organizácia!",
"DeveloperCount": "Pridelené / celkový počet vývojárov",
"QuestionCount": "Zostávajúce / všetky otázky",
"Unlimited": "Neobmedzené",
"Owners": "Vlastníci",
"AddMember": "Pridať člena",
"AddOwner": "Pridať vlastníka",
"AddDeveloper": "Pridať vývojára",
"UserName": "Používateľské meno",
"Name": "Názov",
"EmailAddress": "Emailová adresa",
"Developers": "Vývojári",
"LicenseType": "Typ licencie",
"Manage": "Spravovať",
"StartDate": "Dátum začiatku",
"EndDate": "Dátum ukončenia",
"Modules": "Moduly",
"LicenseExtendMessage": "Koniec platnosti vašej licencie je predĺžený do {0}.",
"LicenseUpgradeMessage": "Vaša licencia je aktualizovaná na {0}",
"LicenseAddDeveloperMessage": "{0} vývojári boli pridaní do vašej licencie",
"Volo.AbpIo.Commercial:010004": "Nie je možné nájsť zadaného používateľa! Používateľ musí už byť zaregistrovaný.",
"MyOrganizations": "Moje organizácie",
"ApiKey": "API kľúč",
"UserNameNotFound": "Neexistuje žiadny používateľ s používateľským menom {0}",
"SuccessfullyAddedToNewsletter": "Ďakujeme, že ste sa prihlásili na odber nášho newslettera!",
"MyProfile": "Môj profil",
"EmailNotValid": "Zadajte platnú emailovú adresu.",
"JoinOurMarketingNewsletter": "Prihláste sa na odber reklamného newslettra",
"WouldLikeToReceiveMarketingMaterials": "Chcem dostávať reklamné materiály, ponuky produktov a špeciálne ponuky.",
"StartUsingYourLicenseNow": "Teraz začnite používať svoju licenciu!",
"WelcomePage": "Uvítacia stránka",
"UnsubscriptionExpireEmail": "Odhlásenie z odberu emailov informujúcich o dátume vypršania platnosti licencie",
"UnsubscribeLicenseExpireEmailReminderMessage": "Tento email obsahuje iba pripomenutie dátumu vypršania platnosti vašej licencie.",
"UnsubscribeFromLicenseExpireEmails": "Ak nechcete dostávať emaily o dátume vypršania platnosti vašej licencie, môžete sa kedykoľvek odhlásiť.",
"Unsubscribe": "Odhlásiť",
"NotOrganizationMember": "Nie ste členom žiadnej organizácie.",
"UnsubscribeLicenseExpirationEmailSuccessTitle": "Úspešne odhlásené",
"UnsubscribeLicenseExpirationEmailSuccessMessage": "Už nebudete dostávať emaily s upozornením na dátum vypršania platnosti licencie.",
"IndexPageHeroSection": "<span class=\"first-line\">Kompletná</span><span class=\"second-line\"> web vývojová platforma</span><span class=\"third-line\">postavená na <img src=\"{0}\" width=\"110\" class=\"ml-1\" /> frameworku</span>",
"AbpCommercialShortDescription": "ABP Commercial poskytuje predpripravené aplikačné moduly, nástroje na rýchly vývoj aplikácií, profesionálne témy používateľského rozhrania, prémiovú podporu a ďalšie.",
"LiveDemo": "Live ukážka",
"GetLicence": "Získajte licenciu",
"Application": "Aplikácia",
"StartupTemplates": "Štartovacie šablóny",
"Startup": "Štart",
"Templates": "Šablóny",
"Developer": "Vývojár",
"Tools": "Nástroje",
"Premium": "Premium",
"PremiumSupport": "Prémiová podpora",
"PremiumForumSupport": "Prémiová podpora na fóre",
"UI": "POUŽÍVATEĽSKÉ ROZHRANIE",
"Themes": "Témy",
"JoinOurNewsletter": "Prihláste sa na odber newslettra",
"Send": "Odoslať",
"Learn": "Učiť sa",
"AdditionalServices": "Ďalšie služby",
"WhatIsABPFramework": "ČO JE FRAMEWORK ABP?",
"OpenSourceBaseFramework": "Základný open source framework ",
"ABPFrameworkExplanation": "<p class=\"lead\">ABP Commercial je založené na ABP frameworku, open source a komunitou riadenom frameworku webových aplikácií pre ASP.NET Core.</p><p>ABP Framework poskytuje vynikajúcu infraštruktúru na písanie udržiavateľného, rozšíriteľného a testovateľného kódu s osvedčenými postupmi.</p><p>Je integrovaný a postavený na populárnych nástrojoch, ktoré už poznáte. Nízka krivka učenia, jednoduché prispôsobenie, pohodlný vývoj.</p>",
"Modular": "Modulárny",
"MicroserviceCompatible": "Kompatibilita s mikroslužbami",
"DomainDrivenDesignInfrastructure": "Domain Driven Design infraštruktúra",
"MultiTenancy": "Multitenacia",
"DistributedMessaging": "Distribuované zasielanie správ",
"DynamicProxying": "Dynamický Proxying",
"BackgroundJobs": "Automatické úlohy na pozadí",
"AuditLogging": "Audit logovanie",
"BLOBStoring": "Ukladanie BLOBov",
"BundlingMinification": "Bundling a minifikácia",
"AdvancedLocalization": "Pokročilá lokalizácia",
"ManyMore": "Mnohé ďalšie",
"ExploreTheABPFramework": "Preskúmajte ABP framework",
"WhyUseTheABPCommercial": "Prečo používať ABP Commercial?",
"WhyUseTheABPCommercialExplanation": "<p class=\"lead mt- 5\">Vybudovanie webových aplikácií podnikovej úrovne môže byť zložité a časovo náročné.</p><p>ABP Commercial ponúka dokonalú základnú infraštruktúru potrebnú pre všetky moderné riešenia ASP.NET Core podnikovej úrovne. Celý vývojový cyklus, od návrhu až po nasadenie, umožňujú integrované funkcie a moduly ABP.</p>",
"StartupTemplatesShortDescription": "Štartovacie šablóny vám umožnia spustiť projekt za niekoľko sekúnd.",
"UIFrameworksOptions": "Možnosti používateľského rozhrania frameworku;",
"DatabaseProviderOptions": "Možnosti poskytovateľov databáz;",
"PreBuiltApplicationModules": "Vopred pripravené aplikačné moduly",
"PreBuiltApplicationModulesShortDescription": "Väčšina bežných aplikačných požiadaviek je už pre vás vyvinutá v podobe znovupoužiteľných modulov.",
"Account": "Účet",
"Blogging": "Blogovanie",
"Identity": "Identity",
"IdentityServer": "Identity Server",
"Saas": "Saas",
"LanguageManagement": "Jazykový manažment",
"TextTemplateManagement": "Správa textových šablón",
"See All Modules": "Pozri všetky moduly",
"ABPSuite": "ABP Suite",
"AbpSuiteShortDescription": "ABP Suite je doplnkový nástroj k uABP Commercial.",
"AbpSuiteExplanation": "Umožňuje vytvárať webové stránky v priebehu niekoľkých minút. Je to globálny nástroj .NET Core, ktorý možno nainštalovať z príkazového riadka. Dokáže vytvoriť nové riešenie ABP, generovať CRUD stránky od databázy až po frontend.",
"Details": "Podrobnosti",
"LeptonTheme": "Lepton téma",
"ProfessionalModernUIThemes": "Profesionálne a moderné témy používateľského rozhrania",
"LeptonThemeExplanation": "Lepton poskytuje škálu Bootstrap admin tém, ktoré slúžia ako základ pre akýkoľvek projekt, kde je vyžadovaný administrátorský panel.",
"DefaultTheme": "Predvolená téma",
"MaterialTheme": "Materiál téma",
"Default2Theme": "Predvolená téma 2",
"DarkTheme": "Tmavá téma",
"DarkBlueTheme": "Tmavomodrá téma",
"LightTheme": "Téma Light",
"ProudToWorkWith": "Hrdo spolupracujeme s",
"OurConsumers": "Na ABP Commercial sa spoliehajú stovky podnikov a vývojárov vo viac ako 50 krajinách sveta.",
"JoinOurConsumers": "Pridajte sa k nim a jednoducho vytvorte úžasné produkty.",
"AdditionalServicesExplanation": "Potrebujete ďalšie alebo vlastné služby? <strong>My a naši partneri vám ich môžeme poskytnúť;</strong>",
"CustomProjectDevelopment": "Vývoj projektu na mieru",
"CustomProjectDevelopmentExplanation": "Špecializovaní vývojári pre vaše vlastné projekty.",
"PortingExistingProjects": "Prenos existujúcich projektov",
"PortingExistingProjectsExplanation": "Migrácia starších projektov do ABP frameworku.",
"LiveSupport": "Live podpora",
"LiveSupportExplanation": "V prípade potreby možnosť Live podpory na diaľku.",
"Training": "Školenie",
"TrainingExplanation": "Školenia určené pre vašich vývojárov.",
"OnBoarding": "Rozbehnutie",
"OnBoardingExplanation": "Pomoc pri nastavovaní vývojárskeho prostredia, CI prostredia a CD prostredia.",
"PrioritizedTechnicalSupport": "Prioritná technická podpora",
"PremiumSupportExplanation": "Popri skvelej podpore od komunity ABP frameworku aj náš tím podpory zodpovedá otázky a rieši problémy komerčných zákazníkov s vysokou prioritou.",
"SeeTheSupportOptions": "Pozrite si možnosti podpory",
"Contact": "Kontakt",
"TellUsWhatYouNeed": "Povedzte nám, čo potrebujete.",
"YourMessage": "Vaša správa",
"YourFullName": "Vaše celé meno",
"EmailField": "Emailová adresa",
"YourEmailAddress": "Vaša emailová adresa",
"HowMayWeHelpYou": "Ako vám môžeme pomôcť?",
"SendMessage": "Odoslať správu",
"Success": "Úspech",
"WeWillReplyYou": "Dostali sme vašu správu a čoskoro vás budeme kontaktovať.",
"GoHome": "Prejsť Domov",
"CreateLiveDemo": "Vytvoriť live ukážku",
"RegisterToTheNewsletter": "Zaregistrujte sa na odber noviniek a dostávajte informácie o ABP.IO, vrátane nových verzií atď.",
"EnterYourEmailOrLogin": "Zadajte svoju emailovú adresu a vytvorte si ukážku alebo sa <a href=\"{0}\">prihláste</a> pomocou svojho existujúceho konta.",
"ApplicationTemplate": "Šablóna žiadosti",
"ApplicationTemplateExplanation": "Štartovacia šablóna aplikácie sa používa na vytvorenie novej webovej aplikácie.",
"EfCoreProvider": "Entity Framework (podporuje SQL Server, MySQL, PostgreSQL, Oracle <a href=\"https://docs.microsoft.com/en-us/ef/core/providers/\">a ďalšie</a>)",
"AlreadyIncludedInTemplateModules": "V tejto šablóne sú už zahrnuté a nakonfigurované nasledujúce moduly:",
"ApplicationTemplateArchitecture": "Táto šablóna aplikácie podporuje aj viacúrovňovú architektúru, v ktorej sú fyzicky oddelené vrstva používateľského rozhrania, vrstva API a služba overovania.",
"SeeTheGuideOrGoToTheLiveDemo": "Technické informácie o tejto šablóne nájdete v príručke pre vývojárov alebo v live ukážke.",
"DeveloperGuide": "Príručka pre vývojárov",
"ModuleTemplate": "Šablóna modulu",
"ModuleTemplateExplanation1": "Chcete vytvoriť modul a opätovne ho použiť v iných aplikáciách? Táto štartovacia šablóna pripraví všetko na vytvorenie opakovane použiteľného <strong>aplikačného modulu</strong> alebo <strong>mikroslužby</strong>.",
"ModuleTemplateExplanation2": "<p>Môžete podporovať jeden alebo viacero používateľských rozhraní frameworku, jedného alebo viacerých poskytovateľov databáz pre jeden modul. Štartovacia šablóna je nakonfigurovaná tak, aby okrem infraštruktúry unit a integračných testov spustila a <strong>testovala váš modul</strong> v minimálnej aplikácii. </p> <p>Technické informácie o tejto šablóne nájdete v príručke pre vývojárov.</p>",
"WithAllStyleOptions": "so všetkými možnosťami štýlov",
"Demo": "Ukážka",
"SeeAllModules": "Pozrite si všetky moduly",
"ABPCLIExplanation": "ABP CLI (Command Line Interface) je nástroj v príkazovom riadku na vykonávanie niektorých bežných operácií v riešeniach založených na ABP.",
"ABPSuiteEasilyCURD": "ABP Suite je nástroj, ktorý vám umožňuje jednoducho vytvárať CRUD stránky.",
"WeAreHereToHelp": "Sme tu, aby sme <span class=\"zero-text\">pomohli</span>",
"BrowseOrAskQuestion": "Môžete si prezerať témy našej nápovedy alebo vyhľadávať v často kladených otázkach, prípadne nám môžete položiť otázku pomocou <a href=\"{0}\" class=\"text-success\">kontaktného formulára</a>.",
"SearchQuestionPlaceholder": "Vyhľadávanie v často kladených otázkach",
"WhatIsTheABPCommercial": "Čo je to ABP Commercial?",
"WhatAreDifferencesThanAbpFramework": "Aké sú rozdiely medzi open source ABP Framework a ABP Commercial?",
"ABPCommercialExplanation": "ABP Commercial je súbor prémiových modulov, nástrojov, tém a služieb postavených na open source <a target=\"_blank\" href=\"{0}\">ABP frameworku</a>. ABP Commercial vyvíja a podporuje ten istý tím, ktorý stojí za ABP frameworkom.",
"WhatAreDifferencesThanABPFrameworkExplanation": "<p> <a target=\"_blank\" href=\"{0}\">ABP framework</a> je modulárny, témovo-upraviteľný, s mikroslužbami kompatibilný framework na vývoj aplikácií pre ASP.NET Core. Poskytuje kompletnú architektúru a silnú infraštruktúru, aby ste sa mohli sústrediť na vlastný biznis kód a nemuseli sa opakovať pri každom novom projekte. Je založený na osvedčených postupoch vývoja softvéru a populárnych nástrojoch, ktoré už poznáte. </p> <p> ABP framework je úplne bezplatný, má otvorený zdrojový kód a je poháňaný komunitou. Poskytuje aj bezplatnú tému a niektoré predpripravené moduly (napr. správu identít a správu tenantov).</p>",
"VisitTheFrameworkVSCommercialDocument": "Pre viac informácií navštívte nasledujúci odkaz <a href=\"{0}\" target=\"_blank\"> {1} </a>",
"ABPCommercialFollowingBenefits": "ABP Commercial má oproti ABP systému nasledujúce výhody;",
"Professional": "Profesionálny",
"UIThemes": "Témy používateľského rozhrania",
"EnterpriseModules": "Podnikovo pripravené, funkčne bohaté, predpripravené <a href=\"{0}\">aplikačné moduly</a> (napr. správa Identity Server, správa SaaS, správa jazykov)",
"ToolingToSupport": "Nástroje na podporu produktivity vášho vývoja (napr. <a href=\"{0}\">ABP Suite</a>)",
"PremiumSupportLink": "Prémiová <a href=\"{0}\" target=\"_blank\">podpora</a>",
"WhatDoIDownloadABPCommercial": "Čo si stiahnem, keď si zakúpim ABP Commercial?",
"CreateUnlimitedSolutions": "Po zakúpení licencie ABP Commercial budete môcť vytvárať neobmedzený počet riešení, ako je popísané v dokumente <a href=\"{0}\">Začíname</a>.",
"ABPCommercialSolutionExplanation": "Pri vytváraní novej aplikácie dostanete riešenie vo Visual Studio (štartovaciu šablónu) na základe vašich preferencií. Stiahnuté riešenie má pre vás už nainštalované a nakonfigurované komerčné moduly a témy. Ak budete chcieť, môžete odstrániť predinštalovaný modul alebo pridať iný modul. Všetky predvolené moduly a témy používajú balíky NuGet/NPM.",
"StartDevelopWithTutorials": "Stiahnuté riešenie je dobre navrhnuté a zdokumentované. Môžete na jeho základe začať vyvíjať vlastný biznis kód podľa <a href=\"{0}\">návodov</a>",
"TryTheCommercialDemo": "Môžete vyskúšať <a href=\"{0}\">demo</a> a pozrieť si ukážku aplikácie vytvorenej pomocou štartovacej šablóny ABP Commercial.",
"HowManyProducts": "Koľko rôznych produktov/riešení môžem vytvoriť pomocou ABP Commercial?",
"HowManyProductsExplanation": "Vytvorenie projektu ABP nie je obmedzené. Môžete vytvoriť toľko projektov, koľko chcete, vyvíjať ich a nahrávať na rôzne servery.",
"HowManyDevelopers": "Koľko vývojárov môže pracovať na ABP Commercial?",
"HowManyDevelopersExplanation": "Licencie ABP Commercial sú jednotkové na vývojára. Rôzne typy licencií majú rôzne limity pre vývojárov. Ktorýkoľvek typ licencie však môžete kedykoľvek rozšíriť o ďalších vývojárov. Informácie o typoch licencií, limitoch pre vývojárov a nákladoch na ďalších vývojárov nájdete na stránke <a href=\"{0}\">ceny</a>.",
"ChangingLicenseType": "Môžem v budúcnosti zmeniť typ licencie?",
"ChangingLicenseTypeExplanation": "Vždy je možné pridať nových vývojárov v rovnakom type licencie. Pozrite si tiež časť \"Koľko vývojárov môže pracovať na ABP Commercial?\". Môžete tiež prejsť na vyššiu licenciu zaplatením vypočítaného cenového rozdielu. Pri prechode na vyšší licenčný plán získate výhody nového plánu, ale prechodom na vyšší licenčný plán sa nezmení dátum platnosti licencie.",
"LicenseExtendUpgradeDiff": "Aký je rozdiel medzi rozšírením a aktualizáciou licencie?",
"LicenseExtendUpgradeDiffExplanation": "<strong>Predĺženie:</strong> Predĺžením/obnovením licencie budete naďalej dostávať prémiovú podporu a hlavné aktualizácie modulov a tém. Okrem toho budete môcť pokračovať vo vytváraní nových projektov, naďalej používať balík ABP Suite, ktorý urýchľuje váš vývoj. <hr/><strong>Podpísanie licencie:</strong> Rozšírením licencie postúpite na vyšší licenčný plán, ktorý vám umožní získať ďalšie výhody. Pozrite si <a href=\"/pricing\">tabuľku porovnania licencií</a> a skontrolujte rozdiely medzi licenčnými plánmi.<strong>Na druhej strane, pri upgrade sa dátum skončenia platnosti vašej licencie nezmení!</strong> Ak chcete predĺžiť dátum skončenia platnosti vašej licencie, musíte si licenciu predĺžiť.",
"LicenseRenewalCost": "Aké sú náklady na obnovenie licencie po 1 roku?",
"LicenseRenewalCostExplanation": "Sadzba za obnovenie (predĺženie) všetkých trvalých licencií ABP Commercial je {0} z cenníkovej ceny licencie. Cena za obnovenie štandardnej tímovej licencie je {1} USD, štandardnej obchodnej licencie je {2} USD a štandardnej podnikovej licencie je {3} USD. Ak už ste zákazníkom, <a href='{4}' target='_blank'>prihláste sa do svojho konta</a> a prezrite si dostupné ceny za obnovenie.",
"HowDoIRenewMyLicense": "Ako si môžem obnoviť licenciu?",
"HowDoIRenewMyLicenseExplanation": "Svoju licenciu môžete obnoviť tak, že prejdete na stránku <a href='{0}' target='_blank'> správa organizície</a>. Ak chcete využiť naše zľavnené ceny za predčasné obnovenie, uistite sa, že ste licenciu obnovili pred uplynutím jej platnosti. Netrápte sa však tým, že neviete, kedy sa vaša možnosť predčasného obnovenia skončí. Pred vypršaním platnosti predplatného dostanete 2 e-maily s pripomienkami. Budeme ich posielať o 30 dní, teda 7 dní pred vypršaním platnosti.",
"IsSourceCodeIncluded": "Zahŕňa moja licencia zdrojový kód komerčných modulov a tém?",
"IsSourceCodeIncludedExplanation1": "Závisí od typu zakúpenej licencie:",
"IsSourceCodeIncludedExplanation2": "<strong>Tím</strong>: Vaše riešenie používa moduly a témy ako balíky NuGet a NPM. Neobsahuje ich zdrojový kód. Týmto spôsobom môžete tieto moduly a témy ľahko aktualizovať vždy, keď je k dispozícii nová verzia. Nemôžete však získať zdrojový kód modulov a tém.",
"IsSourceCodeIncludedExplanation3": "<strong>Business/Enterprise</strong>: Okrem tímovej licencie si môžete stiahnuť zdrojový kód akéhokoľvek modulu alebo témy, ktorú potrebujete. Môžete dokonca odstrániť odkazy na balíky NuGet/NPM pre konkrétny modul a pridať jeho zdrojový kód priamo do svojho riešenia a úplne ho zmeniť.",
"IsSourceCodeIncludedExplanation4": "<p>Začlenenie zdrojového kódu modulu do vášho riešenia vám dáva maximálnu slobodu prispôsobenia tohto modulu. Potom však nebude možné automaticky aktualizovať modul pri vydaní novej verzie.</p><p>Žiadna z licencií nezahŕňa zdrojový kód balíka ABP Suite, čo je externý nástroj, ktorý pre vás generuje kód a pomáha pri vývoji.</p><p>Dalšie rozdiely medzi jednotlivými typmi licencií nájdete na <a href=\"{0}\">stránke o cenách</a>.</p>",
"ChangingDevelopers": "Môžem v budúcnosti zmeniť registrovaných vývojárov svojej organizácie?",
"ChangingDevelopersExplanation": "Okrem pridávania nových vývojárov do licencie môžete tiež meniť existujúcich vývojárov (môžete odstrániť vývojára a pridať nového na to isté miesto) bez akýchkoľvek ďalších nákladov.",
"WhatHappensWhenLicenseEnds": "Čo sa stane po skončení platnosti licencie?",
"WhatHappensWhenLicenseEndsExplanation1": "Typ komerčnej licencie ABP je <a href=\"{0}\" target=\"_blank\">trvalá licencia</a>. Po uplynutí platnosti licencie môžete pokračovať vo vývoji svojho projektu. A nie ste povinní obnoviť svoju licenciu. Vaša licencia sa dodáva s ročným plánom aktualizácií a podpory už v balení. Ak chcete aj naďalej dostávať nové funkcie, vylepšenia výkonu, opravy chýb, podporu a pokračovať v používaní balíka ABP Suite, nezabudnite si plán každý rok obnoviť. Po skončení platnosti vašej licencie nebudete môcť získať ďalšie z nasledujúcich výhod;",
"WhatHappensWhenLicenseEndsExplanation2": "Pomocou ABP Commercial nemôžete vytvárať nové riešenia, ale navždy môžete pokračovať vo vývoji existujúcich aplikácií.",
"WhatHappensWhenLicenseEndsExplanation3": "Budete môcť získať aktualizácie modulov a tém v rámci vašej hlavnej verzie. Ak napríklad používate modul vo verzii 3.2.0, stále môžete získať aktualizácie pre verziu 3.x.x (v3.3.0, v3.5.2... atď.) tohto modulu. Nemôžete však získať aktualizácie pre ďalšiu hlavnú verziu (napr. v4.x, v5.x).",
"WhatHappensWhenLicenseEndsExplanation4": "Po skončení platnosti vašej licencie nemôžete inštalovať nové moduly a témy pridané do platformy ABP Commercial.",
"WhatHappensWhenLicenseEndsExplanation5": "Balík ABP Suite nemôžete používať.",
"WhatHappensWhenLicenseEndsExplanation6": "Už nemôžete získať <a href=\"{0}\">prémiovú podporu</a>.",
"WhatHappensWhenLicenseEndsExplanation7": "Ak chcete tieto výhody využívať aj naďalej, môžete si predplatné obnoviť. Pri obnovení predplatného sa poskytuje 20 % zľava.",
"WhenShouldIRenewMyLicense": "Kedy si mám obnoviť licenciu?",
"WhenShouldIRenewMyLicenseExplanation1": "Ak si licenciu obnovíte do <strong>1 mesiaca</strong> po vypršaní platnosti licencie, na celkovú cenu licencie bude uplatnená zľava 20%.",
"WhenShouldIRenewMyLicenseExplanation2": "Ak obnovíte licenciu po uplynutí 1 mesiaca od dátumu vypršania platnosti licencie, cena za obnovenie bude rovnaká ako cena za nákup licencie a na obnovenie nebude poskytnutá žiadna zľava.",
"TrialPlan": "Máte skúšobný plán?",
"TrialPlanExplanation": "Spoločnosť ABP Commercial zatiaľ nemá skúšobný plán. Pre tímové licencie poskytujeme 30-dňovú záruku vrátenia peňazí. Stačí požiadať o vrátenie peňazí počas prvých 30 dní. V prípade licencií Business a Enterprise poskytujeme 60% vrátenie peňazí do 30 dní. Je to preto, že licencie Business a Enterprise obsahujú úplný zdrojový kód všetkých modulov a tém.",
"DoYouAcceptBankWireTransfer": "Prijímate bankový prevod?",
"DoYouAcceptBankWireTransferExplanation": "Áno, akceptujeme bankový prevod.<br />Po zaslaní sumy za licenciu bankovým prevodom nám pošlite potvrdenie a požadovaný typ licencie e-mailom.<br />Naše informácie o medzinárodnom bankovom účte:",
"HowToUpgrade": "Ako aktualizovať existujúce aplikácie, keď je k dispozícii nová verzia?",
"HowToUpgradeExplanation1": "Pri vytváraní novej aplikácie pomocou ABP Commercial sa všetky moduly a téma použijú ako balíky NuGet a NPM. Balíky teda môžete ľahko aktualizovať, keď je k dispozícii nová verzia.",
"HowToUpgradeExplanation2": "Okrem štandardných aktualizácií NuGet/NPM poskytuje <a href=\"{0}\">ABP CLI</a> príkaz update, ktorý automaticky nájde a aktualizuje všetky balíky súvisiace s ABP vo vašom riešení.",
"DatabaseSupport": "Ktoré databázové systémy sú podporované?",
"DatabaseSupportExplanation": "Samotný ABP Framework je databázovo agnostický a môže pracovať s akýmkoľvek poskytovateľom databázy. Zoznam aktuálne implementovaných poskytovateľov nájdete v <a href=\"{0}\" target=\"_blank\">dokumente o prístupe k údajom</a>.",
"UISupport": "Ktoré používateľské rozhrania frameworku sú podporované?",
"Supported": "Podporované",
"UISupportExplanation": "Samotný ABP framework je agnostický a môže pracovať s akýmkoľvek UI frameworkom. Štartovacie šablóny, moduly používateľského rozhrania a témy však neboli implementované pre všetky UI frameworky. Aktuálny zoznam možností používateľského rozhrania nájdete v <a href=\"{0}\">dokumente Začíname</a>.",
"MicroserviceSupport": "Podporuje architektúru mikroslužieb?",
"MicroserviceSupportExplanation1": "Jedným z hlavných cieľov ABP frameworku je poskytnúť vhodnú infraštruktúru na vytváranie riešení mikroslužieb. Na lepšie pochopenie si pozrite dokument <a href=\"{0}\">architektúra mikroslužieb</a>.",
"MicroserviceSupportExplanation2": "Všetky komerčné moduly ABP sú navrhnuté tak, aby podporovali scenáre nasadenia mikroslužieb (s vlastnou API a databázou) podľa dokumentu <a href=\"{0}\">Osvedčené postupy vývoja modulov</a>.",
"MicroserviceSupportExplanation3": "Poskytujeme vzorové <a href=\"{0}\">micro-service demo riešenie</a>, ktoré demonštruje implementáciu architektúry mikroslužby a pomôže vám vytvoriť vlastné riešenie.",
"MicroserviceSupportExplanation4": "Krátka odpoveď teda znie \"<strong>áno, podporuje architektúru mikroslužieb</strong>\".",
"MicroserviceSupportExplanation5": "Riešenie je systém mikroslužieb a každé riešenie má iné požiadavky, sieťovú topológiu, komunikačné scenáre, možnosti autentifikácie, databázové rozdelenia/zdieľanie databáz, runtime konfigurácie, integrácie systémov tretích strán a mnohé ďalšie.",
"MicroserviceSupportExplanation6": "ABP Framework a ABP Commercial poskytujú infraštruktúru pre scenáre mikroslužieb, moduly kompatibilné s mikroslužbami, vzorky a dokumentáciu, ktoré vám pomôžu vytvoriť vlastné riešenie. Neočakávajte však, že si priamo stiahnete svoje vysnívané riešenie, ktoré je pre vás vopred zostavené. Budete mu musieť porozumieť a spojiť niektoré časti na základe vašich požiadaviek.",
"WhereCanIDownloadSourceCode": "Kde si môžem stiahnuť zdrojový kód?",
"WhereCanIDownloadSourceCodeExplanation": "Zdrojový kód všetkých modulov ABP, balíkov Angular a tém si môžete stiahnuť prostredníctvom balíka ABP Suite alebo ABP CLI. Pozrite si <a href=\"{0}\">Ako stiahnuť zdrojový kód?</a>",
"ComputerLimitation": "Koľko počítačov môže vývojár prihlásiť pri vývoji ABP?",
"ComputerLimitationExplanation": "Osobitne povoľujeme <strong>{0} počítačov</strong> na jednotlivca/licencovaného vývojára. Vždy, keď je potrebné, aby vývojár vyvíjal komerčné ABP produkty na treťom počítači, je potrebné poslať e-mail na adresu license@abp.io s vysvetlením situácie a my potom vykonáme príslušné pridelenie v našom systéme.",
"RefundPolicy": "Máte podmienky vrátenia peňazí?",
"RefundPolicyExplanation": "O vrátenie peňazí môžete požiadať do <strong>30 dní</strong> od zakúpenia licencie. Typy licencií Business a Enterprise majú možnosť stiahnutia zdrojového kódu, preto nie je možné vrátiť peniaze za licencie Business a Enterprise (a všetky licencie, ktoré zahŕňajú právo na získanie zdrojového kódu). Okrem toho sa nevracajú peniaze za obnovenie a druhý nákup licencie.",
"HowCanIRefundVat": "Ako môžem vrátiť DPH?",
"HowCanIRefundVatExplanation1": "Ak ste platbu uskutočnili prostredníctvom služby 2Checkout, DPH môžete vrátiť prostredníctvom svojho účtu 2Checkout:",
"HowCanIRefundVatExplanation2": "Prihláste sa do svojho účtu <a href=\"https://secure.2checkout.com/cpanel/login.php\" target=\"_blank\">2Checkout</a>",
"HowCanIRefundVatExplanation3": "Vyhľadajte príslušnú objednávku a stlačte tlačidlo \"Vrátiť oneskorenú DPH\" (zadajte svoje IČ DPH).",
"HowCanIGetMyInvoice": "Ako môžem získať faktúru?",
"HowCanIGetMyInvoiceExplanation": "Na zakúpenie licencie sú k dispozícii 2 platobné brány: PayU a 2Checkout. Ak si zakúpite licenciu prostredníctvom brány 2Checkout, odošle vám faktúru vo formáte PDF na vašu e-mailovú adresu, pozrite si <a href=\"https://knowledgecenter.2checkout.com/Documentation/03Billing-and-payments/Payment-operations/How-do-invoices-work\">fakturovanie cez 2Checkout.</a> Ak si zakúpite licenciu prostredníctvom brány PayU alebo bankovým prevodom, pripravíme a pošleme vám faktúru. O faktúru môžete požiadať na stránke <a href=\"{0}\">správy organizácie.</a>",
"Forum": "Fórum",
"SupportExplanation": "Komerčné ABP licencie poskytujú prémiovú podporu fóra zloženú z tímu odborníkov na ABP Framework.",
"PrivateTicket": "Privátny ticket",
"PrivateTicketExplanation": "Licencia Enterprise zahŕňa aj súkromnú podporu e-mailom a ticket systém.",
"AbpSuiteExplanation1": "Sada ABP Suite umožňuje vytvárať webové stránky v priebehu niekoľkých minút. Je to globálny nástroj .NET Core, ktorý možno nainštalovať z príkazového riadka.",
"AbpSuiteExplanation2": "Môže vytvoriť nové riešenie ABP, generovať stránky CRUD z databázy do front-endu. Technický prehľad nájdete v <a href=\"{0}\">dokumente</a>",
"FastEasy": "Rýchlo & jednoducho",
"AbpSuiteExplanation3": "Sada ABP Suite umožňuje jednoducho vytvárať CRUD stránky. Stačí definovať vašu entitu a jej vlastnosti, ostatné nechajte na ABP Suite! Sada ABP Suite vygeneruje všetok potrebný kód pre vašu CRUD stránku za niekoľko sekúnd. Podporuje používateľské rozhrania Angular, MVC a Blazor.",
"RichOptions": "Bohaté možnosti",
"AbpSuiteExplanation4": "ABP Suite podporuje viacero možností používateľského rozhrania, ako napríklad <a href=\"https://docs.microsoft.com/en-us/aspnet/core/razor-pages\">Razor Pages</a> a <a href=\"https://angular.io\">Angular</a>. Podporuje tiež viacero databáz, ako napríklad <a href=\"https://www.mongodb.com\">MongoDB</a> a všetky databázy podporované <strong>EntityFramework Core</strong> (MS SQL Server, Oracle, MySql, PostgreSQL a <a href=\"https://docs.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli\">ďalšie</a>).",
"AbpSuiteExplanation5": "Dobré je, že sa o tieto možnosti nemusíte starať. ABP Suite rozumie typu vášho projektu a vygeneruje kód pre váš projekt a umiestni vygenerovaný kód na správne miesto vo vašom projekte.",
"SourceCode": "Zdrojový kód",
"AbpSuiteExplanation6": "ABP Suite generuje zdrojový kód za vás! Nevygeneruje magické súbory na generovanie webovej stránky. ABP Suite vygeneruje zdrojový kód pre <strong>Entity, repozitáre, aplication service, Code First Migration, JavaScript/TypeScript a CSHTML/HTML</strong> a tiež potrebné rozhrania. ABP Suite tiež generuje kód podľa <strong>Najlepších postupov</strong> vývoja softvéru, takže sa nemusíte obávať o kvalitu vygenerovaného kódu.",
"AbpSuiteExplanation7": "Pretože máte zdrojový kód stavebných blokov vygenerovanej stránky CRUD v správnych aplikačných vrstvách, môžete zdrojový kód jednoducho upraviť a do vygenerovaného kódu vložiť vlastnú/obslužnú logiku.",
"CrossPlatform": "Naprieč platformami",
"AbpSuiteExplanation8": "ABP Suite je vytvorená pomocou .NET Core a je multiplatformová. Spustí sa ako webová aplikácia na vašom lokálnom počítači. Môžete ju spustiť na <strong>Windowse</strong>, <strong>Macu</strong> a <strong>Linuxe</strong>.",
"OtherFeatures": "Ďalšie funkcie",
"OtherFeatures1": "Ľahko aktualizuje balíky <strong>NuGet</strong> a <strong>NPM</strong> na vašom riešení.",
"OtherFeatures2": "Obnovte už vygenerované stránky od začiatku.",
"OtherFeatures3": "Vytvára nové riešenia",
"ThanksForCreatingProject": "Ďakujeme za vytvorenie projektu!",
"HotToRunSolution": "Ako spustiť vaše riešenie?",
"HotToRunSolutionExplanation": "Pozrite si dokument Začíname a dozviete sa, ako nakonfigurovať a spustiť riešenie.",
"GettingStarted": "Začíname",
"WebAppDevTutorial": "Webová aplikácia Dev Tutorial",
"WebAppDevTutorialExplanation": "Pozrite si dokument s návodom na vývoj webovej aplikácie, kde nájdete ukážku vývoja krok za krokom.",
"Document": "Dokument",
"UsingABPSuiteToCURD": "Použite ABP Suite na generovanie CRUD stránok a nástrojov",
"SeeABPSuiteDocument": "Pozrite si dokument ABP Suite, v ktorom sa dozviete o používaní ABP Suite.",
"AskQuestionsOnSupport": "Otázky môžete klásť na stránke ABP Commercial Support.",
"Documentation": "Dokumentácia",
"SeeModulesDocument": "Zoznam všetkých komerčných (pro) modulov a ich dokumentov nájdete v dokumente Moduly.",
"Pricing": "Cenotvorba",
"PricingExplanation": "Vyberte si funkcie a vlastnosti, ktoré vaša firma potrebuje. V prípade rastu ju môžete ľahko upgradovať.",
"Team": "Tím",
"Business": "Obchod",
"Enterprise": "Podnik",
"Custom": "Vlastné",
"IncludedDeveloperLicenses": "Zahrnuté licencie pre vývojárov",
"CustomLicenceOrAdditionalServices": "Potrebujete vlastnú licenciu alebo ďalšie služby?",
"CustomOrVolumeLicense": "Vlastná alebo objemová licencia",
"LiveTrainingSupport": "Live školenia a podpora",
"AndMore": "a viac",
"AdditionalDeveloperLicense": "Dodatočná licencia pre vývojárov",
"ProjectCount": "Počet projektov",
"AllProModules": "Všetky PRO moduly",
"AllProThemes": "Všetky PRO témy",
"AllProStartupTemplates": "Všetky PRO štartovacie šablóny",
"SourceCodeOfAllModules": "Zdrojový kód všetkých modulov",
"SourceCodeOfAllThemes": "Zdrojový kód všetkých tém",
"PerpetualLicense": "Trvalá licencia",
"UnlimitedServerDeployment": "Neobmedzené nasadenie servera",
"YearUpgrade": "Aktualizácia na 1 rok",
"YearPremiumForumSupport": "1 rok prémiovej podpory fóra",
"ForumSupportIncidentCountYear": "Počet incidentov podpory fóra/rok",
"PrivateTicketEmailSupport": "Súkromné tickety & e-mailová podpora",
"BuyNow": "Kúpiť teraz",
"PayViaAmexCard": "Ako môžem platiť kartou AMEX?",
"PayViaAmexCardDescription": "Predvolená platobná brána \"Iyzico\" môže odmietnuť niektoré kreditné karty AMEX z dôvodu bezpečnostných opatrení. V takom prípade môžete platiť prostredníctvom alternatívnej platobnej brány \"2Checkout\".",
"ThankYou": "Ďakujem",
"InvalidReCaptchaErrorMessage": "Pri overovaní reCAPTCHA došlo k chybe. Skúste to znova prosím."
}
}

147
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json

@ -0,0 +1,147 @@
{
"culture": "sk",
"texts": {
"Permission:CommunityArticle": "Článok komunity",
"Permission:Edit": "Upraviť",
"Waiting": "Čakajte",
"Approved": "Schválené",
"Rejected": "Zamietnuté",
"Wait": "Čakajte",
"Approve": "Schváliť",
"Reject": "Zamietnuť",
"ReadArticle": "Prečítajte si článok",
"Status": "Stav",
"ContentSource": "Zdroj obsahu",
"Details": "Podrobnosti",
"Url": "URL",
"Title": "Názov",
"CreationTime": "Čas vytvorenia",
"Save": "Uložiť",
"SameUrlAlreadyExist": "Rovnaká URL už existuje, ak chcete pridať tento článok, mali by ste zmeniť URL!",
"UrlIsNotValid": "URL nie je platná.",
"UrlNotFound": "URL adresa nebola nájdená.",
"UrlContentNotFound": "Obsah URL sa nenašiel.",
"Summary": "Zhrnutie",
"MostRead": "Najčastejšie čítané",
"Latest": "Najnovšie",
"ContributeAbpCommunity": "Prispieť do ABPkomunity",
"SubmitYourArticle": "Odoslanie príspevku",
"ContributionGuide": "Sprievodca príspevkami",
"BugReport": "Bug report",
"SeeAllArticles": "Zobraziť všetky príspevky",
"WelcomeToABPCommunity!": "Vitajte v ABP komunite!",
"MyProfile": "Môj profil",
"MyOrganizations": "Moje organizácie",
"EmailNotValid": "Zadajte platnú e-mailovú adresu.",
"FeatureRequest": "Nová funkčnosť",
"CreateArticleTitleInfo": "Názov príspevku, ktorý sa má zobraziť nad zoznamom príspevkov.",
"CreateArticleSummaryInfo": "Krátke zhrnutie príspevku, ktoré sa zobrazí nad zoznamom príspevkov.",
"CreateArticleCoverInfo": "Ak chcete vytvoriť efektívny článok, pridajte titulnú fotografiu. Pre optimálne zobrazenie nahrávajte obrázky s pomerom strán 16:9. Maximálna veľkosť súboru: 1 MB.",
"ThisExtensionIsNotAllowed": "Toto rozšírenie nie je povolené.",
"TheFileIsTooLarge": "Súbor je príliš veľký.",
"GoToTheArticle": "Prejsť na článok",
"Contribute": "Prispieť",
"OverallProgress": "Celkový pokrok",
"Done": "Hotovo",
"Open": "Otvoriť",
"Closed": "Uzavreté",
"LatestQuestionOnThe": "Posledná otázka",
"Stackoverflow": "Pretečenie zásobníka",
"Votes": "hlasy",
"Answer": "Odpoveď",
"Views": "zobrazenia",
"Answered": "Zodpovedané",
"WaitingForYourAnswer": "Čakáme na vašu odpoveď",
"Asked": "Otázka znela",
"AllQuestions": "Všetky otázky",
"NextVersion": "Ďalšia verzia",
"MilestoneErrorMessage": "Nepodarilo sa získať detaily current milestone z Githubu.",
"QuestionItemErrorMessage": "Z dôvodu pretečenia zísobníka nie je možné načítať detaily poslednej otázky.",
"Oops": "Ups!",
"CreateArticleSuccessMessage": "Článok bol úspešne odoslaný. Bude uverejnený po kontrole administrátorom stránky.",
"ChooseCoverImage": "Vyberte si titulný obrázok...",
"CoverImage": "Obrázok obálky",
"ShareYourExperiencesWithTheABPFramework": "Podeľte sa o svoje skúsenosti s ABP frameworkom!",
"Optional": "Voliteľné",
"UpdateUserWebSiteInfo": "Príklad: https://johndoe.com",
"UpdateUserTwitterInfo": "Príklad: johndoe",
"UpdateUserGithubInfo": "Príklad: johndoe",
"UpdateUserLinkedinInfo": "Príklad: https://www.linkedin.com/...",
"UpdateUserCompanyInfo": "Príklad: Volosoft",
"UpdateUserJobTitleInfo": "Príklad: Vývojár softvéru",
"UserName": "Meno používateľa",
"Company": "Spoločnosť",
"PersonalWebsite": "Osobná webová stránka",
"RegistrationDate": "Dátum registrácie",
"Social": "Sociálna sieť",
"Biography": "Životopis",
"HasNoPublishedArticlesYet": "zatiaľ nemá publikované žiadne články",
"Author": "Autor",
"LatestGithubAnnouncements": "Najnovšie oznámenia Githubu",
"SeeAllAnnouncements": "Pozrite si všetky oznámenia",
"LatestBlogPost": "Najnovší príspevok na blogu",
"Edit": "Upraviť",
"ProfileImageChange": "Zmeniť profilový obrázok",
"BlogItemErrorMessage": "Z ABP nie je možné načítať posledné zmeny príspevku na blogu.",
"PlannedReleaseDate": "Plánovaný dátum nového vydania",
"CommunityArticleRequestErrorMessage": "Nepodarilo sa načítať najnovšiu požiadavku na článok z Githubu.",
"ArticleRequestFromGithubIssue": "Nie sú žiadne žiadosti o článok.",
"LatestArticles": "Posledne pridané príspevky",
"ArticleRequests": "Žiadané články",
"AllArticleRequests": "Zobraziť všetky žiadosti o články",
"SubscribeToTheNewsletter": "Prihlásiť sa k odberu noviniek",
"NewsletterEmailDefinition": "Získajte informácie o dianí v ABP, ako sú nové vydania, bezplatné zdroje, články a ďalšie.",
"NoThanks": "Nie, ďakujem",
"MaybeLater": "Možno neskôr",
"JoinOurArticleNewsletter": "Pripojte sa k odberu noviniek",
"Community": "Komunita",
"Marketing": "Marketing",
"CommunityPrivacyPolicyConfirmation": "Súhlasím so zmluvnými podmienkami a <a href=\"https://commercial.abp.io/Privacy\">zásadami ochrany osobných údajov</a>.",
"ArticleRequestMessageTitle": "<a href=\"https://github.com/abpframework/abp/issues/new\">Otvorte problém</a> na GitHube a požiadajte o článok/návod, ktorý chcete vidieť na tejto webovej stránke.",
"ArticleRequestMessageBody": "Tu je zoznam požadovaných článkov komunity. Chcete napísať požadovaný článok? Kliknite na žiadosť a zapojte sa do diskusie.",
"Language": "Jazyk",
"CreateArticleLanguageInfo": "Jazyk pre obsah príspevku.",
"VideoPost": "Video príspevok",
"Article": "Článok",
"Read": "Prečítajte si",
"CreateGithubArticleUrlInfo": "Pôvodná URL adresa GitHub článku.",
"CreateVideoContentUrlInfo": "Pôvodná URL adresa príspevku na Youtube.",
"CreateExternalArticleUrlInfo": "Pôvodná externá URL adresa článku.",
"VideoContentForm": "Odoslanie videa na YouTube",
"GithubPostForm": "Odoslanie článku na GitHub",
"ExternalPostForm": "Odoslanie externého obsahu",
"HowToPost": "Ako zverejňovať príspevky?",
"Posts": "Príspevky",
"VideoUrl": "URL adresa videa",
"GithubArticleUrl": "URL článku na Githube ",
"ExternalArticleUrl": "URL externého článku",
"CreatePostCoverInfo": "Ak chcete vytvoriť efektívny príspevok, pridajte titulnú fotografiu. Pre optimálne zobrazenie nahrávajte obrázky s pomerom strán 16:9. Maximálna veľkosť súboru: 1 MB.",
"ThankYouForContribution": "Ďakujeme, že ste prispeli do ABP komunity.",
"GithubArticle": "Článok na Githube",
"GithubArticleSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Napíšte článok v ľubovoľnom verejnom repozitári GitHub vo formáte Markdown. <a target=\"_blank\" href=\"https://github.com/abpframework/abp/blob/dev/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md\">príklad</a>",
"GithubArticleSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Odoslať URL adresu článku pomocou formulára.",
"GithubArticleSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Váš článok sa zobrazí na tejto webovej stránke.",
"YoutubeVideo": "Video na YouTube",
"YoutubeVideoSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Uverejnite svoje video na YouTube.",
"YoutubeVideoSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Odoslať URL adresu videa pomocou formulára.",
"YoutubeVideoSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Návštevníci budú môcť sledovať váš video obsah priamo na tejto webovej stránke.",
"ExternalContent": "Externý obsah",
"ExternalContentSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Vytvorte obsah na akejkoľvek verejnej platforme (médium, vlastný blog alebo kdekoľvek chcete).",
"ExternalContentSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Pomocou formulára odošlite URL adresu obsahu.",
"ExternalContentSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Návštevníci sú presmerovaní na obsah pôvodnej webovej stránky.",
"ChooseYourContentType": "Vyberte si spôsob, akým chcete pridať obsah.",
"PostContentViaGithub": "Chcem pridať svoj článok s <span class=\"font-weight-bold\"><i class=\"fa fa-github\"></i> GitHub</span> v súlade s markdown pravidlami.",
"PostContentViaYoutube": "Chcem sa podeliť o svoje videá dostupné na <span class=\"font-weight-bold\"><i class=\"fa fa-youtube\"></i> Youtube</span> tu.",
"PostContentViaExternalSource": "Chcem sem pridať obsah, ktorý som uverejnil na <span class=\"font-weight-bold\">inej platforme</span>.",
"GitHubUserNameValidationMessage": "Vaše používateľské Github meno nesmie obsahovať medzery, uistite sa, že vaše používateľské Github meno je správne.",
"PersonalSiteUrlValidationMessage": "URL adresa vašej osobnej stránky nesmie obsahovať medzery. Uistite sa, že URL adresa vašej osobnej stránky je správna.",
"TwitterUserNameValidationMessage": "Vaše používateľské meno na Twitteri nesmie obsahovať prázdne znaky. Uistite sa, že je vaše používateľské meno na Twitteri správne.",
"LinkedinUrlValidationMessage": "Vaša adresa URL na sieti Linkedin nesmie obsahovať prázdne znaky. Uistite sa, že vaša URL adresa na sieti Linkedin je správna.",
"NoPostsFound": "Nenašli sa žiadne príspevky!",
"SearchInPosts": "Vyhľadávanie v príspevkoch...",
"MinimumSearchContent": "Musíte zadať aspoň 3 znaky!",
"Volo.AbpIo.Domain:060001": "Zdrojová URL(\"{ArticleUrl}\") nie je URL Githubu",
"Volo.AbpIo.Domain:060002": "Obsah článku nie je dostupný v Github zdroji(\"{ArticleUrl}\").",
"Volo.AbpIo.Domain:060003": "Nenašiel sa žiadny obsah článku!"
}
}

202
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json

@ -0,0 +1,202 @@
{
"culture": "sk",
"texts": {
"GetStarted": "Začíname - štartovacie šablóny",
"Create": "Vytvoriť",
"NewProject": "Nový projekt",
"DirectDownload": "Priame stiahnutie",
"ProjectName": "Názov projektu",
"ProjectType": "Typ projektu",
"DatabaseProvider": "Poskytovateľ databázy",
"DatabaseManagementSystem": "Systém správy databáz",
"NTier": "N-úroveň",
"IncludeUserInterface": "Zahrnúť používateľské rozhranie",
"CreateNow": "Vytvoriť teraz",
"TheStartupProject": "Štartovací projekt",
"Tutorial": "Návod",
"UsingCLI": "Pomocou CLI",
"SeeDetails": "Pozri podrobnosti",
"AbpShortDescription": "ABP Framework je kompletná infraštruktúra na vytváranie moderných webových aplikácií podľa najlepších postupov a konvencií vývoja softvéru.",
"SourceCodeUpper": "ZDROJOVÝ KÓD",
"LatestReleaseLogs": "Najnovšie release logy",
"Infrastructure": "Infraštruktúra",
"Architecture": "Architektúra",
"Modular": "Modulárne",
"DontRepeatYourself": "Neopakujte sa",
"DeveloperFocused": "Zameranie na vývojárov",
"FullStackApplicationInfrastructure": "Kompletná infraštruktúra aplikácie.",
"DomainDrivenDesign": "Domain Driven Design",
"DomainDrivenDesignExplanation": "Navrhnuté a vyvinuté na základe vzorov a princípov DDD. Poskytuje vrstvený model pre vašu aplikáciu.",
"Authorization": "Autorizácia",
"AuthorizationExplanation": "Pokročilá autorizácia so systémom používateľov, rolí a jemných oprávnení. Postavené na knižnici Microsoft Identity.",
"MultiTenancy": "Multitenantnosť",
"MultiTenancyExplanationShort": "Jednoduché aplikácie SaaS! Integrovaná multitenantnosť od databázy po používateľské rozhranie.",
"CrossCuttingConcerns": "Cross Cutting Concerns",
"CrossCuttingConcernsExplanationShort": "Kompletná infraštruktúra pre autorizáciu, validáciu, spracovanie výnimiek, ukladanie do vyrovnávacej pamäte, audit logovania, správu transakcií a ďalšie.",
"BuiltInBundlingMinification": "Zabudovaná Bundling & Minification",
"BuiltInBundlingMinificationExplanation": "Nie je potrebné používať externé nástroje na Bundling & Minification. ABP ponúka zabudovaný jednoduchší, dynamický, výkonný a modulárny spôsob!",
"VirtualFileSystem": "Virtuálny systém súborov",
"VirtualFileSystemExplanation": "Vkladanie pohľadov, skriptov, štýlov, obrázkov... do balíkov/knižníc a ich opakované použitie v rôznych aplikáciách.",
"Theming": "Prispôsobenie témy",
"ThemingExplanationShort": "Použite a prispôsobte si štandardnú tému používateľského rozhrania založenú na bootstrape alebo si vytvorte vlastnú.",
"BootstrapTagHelpersDynamicForms": "Tag Bootstrap pomocníci & dynamické formuláre",
"BootstrapTagHelpersDynamicFormsExplanation": "Namiesto ručného písania opakujúcich sa detailov bootstrap komponentov použite ABP tags pomocníkov pre zjednodušenie a výhody intellisense. Vytvárajte formuláre používateľského rozhrania na základe C# modelu použitím dynamického form tag pomocníka.",
"HTTPAPIsDynamicProxies": "HTTP APIs & Dynamic Proxies",
"HTTPAPIsDynamicProxiesExplanation": "Automaticky poskytuje applikačné rozhranie formou REST a HTTP APIs a spracuváva ich pomocou dynamických JavaScriptov and C# proxies.",
"CompleteArchitectureInfo": "Moderná architektúra na vytváranie udržateľných softvérových riešení.",
"DomainDrivenDesignBasedLayeringModelExplanation": "Pomôže vám implementovať DDD architektúru založenú na vrstvách a vytvoriť udržateľnú kódovú základňu.",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Poskytuje štartovacie šablóny, abstrakcie, základné triedy, servicies, dokumentáciu a príručky, ktoré vám pomôžu pri vývoji aplikácie založenej na DDD patteroch & princípoch.",
"MicroserviceCompatibleModelExplanation": "Core framework a predpripravené moduly sú navrhnuté s ohľadom na architektúru mikroslužieb.",
"MicroserviceCompatibleModelExplanationCont": "Poskytuje infraštruktúru, integrácie, vzorky a dokumentáciu na jednoduchšiu implementáciu mikroslužieb, pri monolitickej aplikácii žiadne zložité riešenia.",
"ModularInfo": "ABP poskytuje systém modulov, ktorý umožňuje vyvíjať opakovane použiteľné moduly aplikácie, prepojiť ich s udalosťami životného cyklu aplikácie a vyjadriť závislosti medzi základnými časťami systému.",
"PreBuiltModulesThemes": "Vopred vytvorené moduly a témy",
"PreBuiltModulesThemesExplanation": "Open source a komerčné moduly & témy sú pripravené na použitie vo vašej firemnej aplikácii.",
"NuGetNPMPackages": "Balíky NuGet a NPM balíky",
"NuGetNPMPackagesExplanation": "Distribuované ako balíky NuGet a NPM. Jednoduchá inštalácia a aktualizácia.",
"ExtensibleReplaceable": "Rozšíriteľné/zameniteľné",
"ExtensibleReplaceableExplanation": "Všetky služby a moduly sú navrhnuté s ohľadom na rozšíriteľnosť. Môžete nahradiť služby, stránky, štýly a komponenty.",
"CrossCuttingConcernsExplanation2": "Udržujte svoju kódovú základňu menšiu, aby ste sa mohli sústrediť na kód, ktorý je špecifický pre váš biznis.",
"CrossCuttingConcernsExplanation3": "Nemíňajte čas implementáciou spoločných aplikačných požiadaviek vo viacerých projektoch.",
"AuthenticationAuthorization": "Overovanie a autorizácia",
"ExceptionHandling": "Spracovanie výnimiek",
"Validation": "Overovanie",
"DatabaseConnection": "Pripojenie k databáze",
"TransactionManagement": "Správa transakcií",
"AuditLogging": "Audit logy",
"Caching": "Ukladanie do vyrovnávacej pamäte",
"Multitenancy": "Multitenancia",
"DataFiltering": "Filtrovanie údajov",
"ConventionOverConfiguration": "Konvencia nad konfiguráciou",
"ConventionOverConfigurationExplanation": "ABP implementuje bežné aplikačné konvencie v predvolenom nastavení s minimálnou alebo nulovou konfiguráciou.",
"ConventionOverConfigurationExplanationList1": "Automaticky registruje známe services do dependecy injection.",
"ConventionOverConfigurationExplanationList2": "Poskytuje aplikačné rozhranie formou HTTP API podľa naming conventions.",
"ConventionOverConfigurationExplanationList3": "Vytvára dynamické HTTP client proxies pre jazyky C# a JavaScript.",
"ConventionOverConfigurationExplanationList4": "Poskytuje predvolené úložiská pre vaše entity.",
"ConventionOverConfigurationExplanationList5": "Spravuje jednotku práce na webovú požiadavku alebo metódu aplikačnej služby.",
"ConventionOverConfigurationExplanationList6": "Publikuje vytváranie, aktualizovanie & vymazanie udalostí pre vaše entity.",
"BaseClasses": "Základné triedy",
"BaseClassesExplanation": "Predpripravené základné triedy pre bežné aplikačné patterny.",
"DeveloperFocusedExplanation": "ABP je pre vývojárov.",
"DeveloperFocusedExplanationCont": "Jeho cieľom je zjednodušiť každodenný vývoj softvéru a zároveň vás neobmedzovať pri písaní nízkoúrovňového kódu.",
"SeeAllFeatures": "Pozrite si všetky funkcie",
"CLI_CommandLineInterface": "CLI (rozhranie príkazového riadka)",
"CLI_CommandLineInterfaceExplanation": "Obsahuje CLI, ktoré vám pomôže automatizovať vytváranie nových projektov a pridávanie nových modulov.",
"StartupTemplates": "Štartovacie šablóny",
"StartupTemplatesExplanation": "Rôzne štartovacie šablóny poskytujú plne nakonfigurované riešenie na začatie vývoja.",
"BasedOnFamiliarTools": "Na základe známych nástrojov",
"BasedOnFamiliarToolsExplanation": "Integrované a postavené na obľúbených nástrojoch. Nízka krivka učenia, jednoduché prispôsobenie, pohodlný vývoj.",
"ORMIndependent": "Nezávislé ORM",
"ORMIndependentExplanation": "Core frameworku je ORM/databázovo nezávislý a môže pracovať s akýmkoľvek zdrojom údajov. Entity Framework Core a MongoDB poskytovatelia sú už k dispozícii.",
"Features": "Preskúmajte funkcie ABP frameworku",
"ABPCLI": "ABP CLI",
"Modularity": "Modularita",
"BootstrapTagHelpers": "Bootstrap Tag pomocník",
"DynamicForms": "Dynamické formuláre",
"BundlingMinification": "Bundling & Minification",
"BackgroundJobs": "Automatické úlohy na pozadí",
"BackgroundJobsExplanation": "Definujte jednoduché triedy na vykonávanie automatických úloh na pozadí. Použite vstavaného správcu úloh alebo integrujte vlastného. <a href=\"{0}\">Hangfire</a> & <a href=\"{1}\">RabbitMQ</a> integrácie sú už k dispozícii.",
"DDDInfrastructure": "DDD infraštruktúra",
"DomainDrivenDesignInfrastructure": "Domain Driven Design infraštruktúra",
"AutoRESTAPIs": "Auto Rest APIs",
"DynamicClientProxies": "Dynamic Client Proxies",
"DistributedEventBus": "Distribuovaná zbernica udalostí",
"DistributedEventBusWithRabbitMQIntegration": "Distribuovaná zbernica udalostí s integráciou RabbitMQ",
"TestInfrastructure": "Testovacia infraštruktúra",
"AuditLoggingEntityHistories": "Audit logovanie & história entít",
"ObjectToObjectMapping": "Mapovanie object to object",
"ObjectToObjectMappingExplanation": "<a href=\"{0}\">Mapovanie objekt to object</a> abstrakcia s integráciou AutoMapper.",
"EmailSMSAbstractions": "E-mailové a SMS abstrakcie",
"EmailSMSAbstractionsWithTemplatingSupport": "E-mailové a SMS abstrakcie s podporou šablón",
"Localization": "Lokalizácia",
"SettingManagement": "Manažment nastavenia",
"ExtensionMethods": "Metódy rozšírenia",
"ExtensionMethodsHelpers": "Rozširujúce metódy & pomocníci",
"AspectOrientedProgramming": "Aspektovo orientované programovanie",
"DependencyInjection": "Vstrebávanie závislostí",
"DependencyInjectionByConventions": "Vstrebávanie závislostí podľa konvencií",
"ABPCLIExplanation": "ABP CLI (Command Line Interface) je nástroj príkazového riadka na vykonávanie niektorých bežných operácií pre riešenia založené na ABP.",
"ModularityExplanation": "ABP poskytuje kompletnú infraštruktúru na vytváranie vlastných aplikačných modulov, ktoré môžu obsahovať entity, služby, integráciu databáz, API, komponenty používateľského rozhrania atď.",
"MultiTenancyExplanation": "ABP framework nielenže podporuje vývoj multitenantných aplikácií, ale aj váš kód robí nezávislým od multitenancie.",
"MultiTenancyExplanation2": "Dokáže automaticky určiť aktuálneho tenanta, osobitne izolovať údaje jednotlivých tenantov.",
"MultiTenancyExplanation3": "Podporuje jednu databázu, databázu podľa tentanta a hybridné prístupy.",
"MultiTenancyExplanation4": "Sústreďte sa na svoj biznis kód a nechajte framework, aby sa vo vašom mene postaral o multitenantnosť.",
"BootstrapTagHelpersExplanation": "Namiesto ručného písania opakujúcich sa bootstrap komponentov, použite ABP tag pomocníka na zjednodušenie a využitie výhod intellisense. Bootstrap určite využijete vždy, keď ho budete potrebovať.",
"DynamicFormsExplanation": "Dynamické formuláre & vstup Tag pomocníka môžu vytvoriť kompletný formulár z C# triedy ako modelu.",
"AuthenticationAuthorizationExplanation": "Bohaté možnosti overovania & autorizácie integrované do ASP.NET Core Identity & IdentityServer4. Poskytuje rozšíriteľný a podrobný systém oprávnení.",
"CrossCuttingConcernsExplanation": "Neopakujte sa pri implementácii všetkých týchto bežných vecí znova a znova. Zamerajte sa na svoj biznis kód a nechajte ich automatizovať pomocou konvencií.",
"DatabaseConnectionTransactionManagement": "Pripojenie k databáze & správa transakcií",
"CorrelationIdTracking": "Sledovanie korelačnej identifikácie",
"BundlingMinificationExplanation": "ABP ponúka jednoduchý, dynamický, výkonný, modulárny a zabudovaný bundling & minification system.",
"VirtualFileSystemnExplanation": "Virtuálny sytém súborov umožňuje spravovať súbory, ktoré fyzicky neexistujú v v systéme súborov(na disku). Používa sa najmä na vkladanie (js, css, image, cshtml...) súborov do zostáv a ich používanie ako fyzických súborov za behu.",
"ThemingExplanation": "Systém vytvárania tém umožňuje vyvíjať aplikácie a moduly nezávisle od témy definovaním sady spoločných základných knižníc a layoutov na základe najnovšieho Bootstrap frameworku.",
"DomainDrivenDesignInfrastructureExplanation": "Kompletná infraštruktúra na vytváranie viacvrstvových aplikácií na základe patternov & princípov Domain Driven Design;",
"Specification": "Špecifikácia",
"Repository": "Úložisko",
"DomainService": "Doménová služba",
"ValueObject": "Objektová hodnota",
"ApplicationService": "Aplikačná služba",
"DataTransferObject": "Objekt prenosu údajov",
"AggregateRootEntity": "Aggregate Root, Entity",
"AutoRESTAPIsExplanation": "ABP môže automaticky konfigurovať vaše aplikačné služby ako API Controllers podľa konvencie.",
"DynamicClientProxiesExplanation": "Jednoduché používanie API rozhraní v jazykoch JavaScript a C#.",
"DistributedEventBusWithRabbitMQIntegrationExplanation": "Jednoduché publikovanie a spracuvávanie distribuovaných udalostí pomocou integrovanej zbernice distribuovaných udalostí s dostupnou RabbitMQ integráciou.",
"TestInfrastructureExplanation": "Tento framework bol vyvinutý s ohľadom na unit & integračné testovanie. Na uľahčenie vám poskytuje základné triedy. Štartovacie šablóny sa dodávajú predkonfigurované na testovanie.",
"AuditLoggingEntityHistoriesExplanation": "Zabudované auditové logy pre kritické biznis aplikácie. Audit logovanie, služby, metód a história entít s podrobnosťami na úrovni vlastností.",
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "Abstrakcie IEmailSender a ISmsSender oddeľujú logiku aplikácie od infraštruktúry. Pokročilý systém e-mailových šablón umožňuje vytvárať lokalizované e-mailové šablóny a použiť ich, kedykoľvek je to potrebné.",
"LocalizationExplanation": "Lokalizačný systém umožňuje vytvárať zdroje v jednoduchých JSON súboroch a používať ich na lokalizáciu používateľského rozhrania. Podporuje pokročilé scenáre, ako je dedenie, rozšírenia a integrácia JavaScriptu, pričom je plne kompatibilný s AspNet Core lokalizačným systémom.",
"SettingManagementExplanation": "Definujte nastavenia pre svoju aplikáciu a získajte hodnoty počas behu na základe aktuálnej konfigurácie, tenanta a používateľa.",
"ExtensionMethodsHelpersExplanation": "Neopakujte sa ani pri triviálnych častiach kódu. Vďaka rozšíreniam a pomocníkom pre štandardné typy je váš kód oveľa prehľadnejší a jednoduchší na písanie.",
"AspectOrientedProgrammingExplanation": "Poskytuje pohodlnú infraštruktúru na vytváranie dynamických proxy a implementáciu aspektovo orientovaného programovania. Zachyťte akúkoľvek triedu a vykonajte svoj kód pred a po každom vykonaní metódy.",
"DependencyInjectionByConventionsExplanation": "Nie je potrebné ručne registrovať triedy do dependency injection. Automaticky registruje bežné typy služieb podľa konvencie. Pre ostatné typy služieb môžete použiť rozhrania a atribúty, aby ste to mali jednoduchšie a na jednom mieste.",
"DataFilteringExplanation": "Definujte a používajte dátové filtre, ktoré sa automaticky aplikujú pri vyhľadávaní entít z databázy. Soft Delete & multitenantné filtre sú k dispozícii už v základnej výbave, keď implementujete jednoduché rozhrania.",
"PublishEvents": "Publikovať udalosti",
"HandleEvents": "Spracovanie udalostí",
"AndMore": "a ďalšie...",
"Code": "Kód",
"Result": "Výsledok",
"SeeTheDocumentForMoreInformation": "Viac informácií nájdete v dokumente <a href=\"{1}\">{0}</a>",
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>open source</strong></span><span class=\"second-line text-uppercase\">Web Application<br />Framework </span><span class=\"third-line shine2\"><strong>pre asp.net core</strong></span>",
"UiFramework": "UI framework",
"EmailAddress": "E-mailová adresa",
"Mobile": "Mobilný",
"ReactNative": "React Native",
"Strong": "Silný",
"Complete": "Kompletné",
"BasedLayeringModel": "Základný model vrstvenia",
"Microservice": "Mikroslužba",
"Compatible": "Kompatibilné",
"MeeTTheABPCommunityInfo": "Naším poslaním je vytvoriť prostredie, v ktorom si vývojári môžu navzájom pomáhať článkami, návodmi, prípadovými štúdiami atď. a stretávať sa s podobne zmýšľajúcimi ľuďmi.",
"JoinTheABPCommunityInfo": "Zapojte sa do živej komunity a staňte sa prispievateľom do ABP frameworku!",
"AllArticles": "Všetky články",
"SubmitYourArticle": "Odoslať článok",
"DynamicClientProxyDocument": "Pozrite si dokumentáciu dynamického proxy klienta pre <a href=\"{0}\">JavaScript</a> a <a href=\"{1}\">C#</a>.",
"EmailSMSAbstractionsDocument": "Viac informácií nájdete v dokumentoch <a href=\"{0}\">posielanie e-mailov</a> a <a href=\"{1}\">posielanie SMS</a>.",
"CreateProjectWizard": "Tento sprievodca vytvorí nový projekt zo štartovacej šablóny, ktorá je správne nakonfigurovaná na začatie vášho projektu.",
"TieredOption": "Vytvára viacúrovňové riešenie, v ktorom sú Web a Http API vrstvy fyzicky oddelené. Ak nie je checkbox začiarknutý, vytvorí vrstvené riešenie, ktoré je menej zložité a vhodné pre väčšinu scenárov.",
"SeparateIdentityServerOption": "Rozdeľuje stranu servera na dve aplikácie: Prvá je určená pre identity server a druhá pre vaše HTTP API na strane servera.",
"UseslatestPreVersion": "Používa najnovšiu predprípravnú verziu",
"ReadTheDocumentation": "<span class=\"text-primary\">Prečítajte si</span><span class=\"text-success\">Dokumentáciu</span>",
"Documentation": "Dokumentácia",
"GettingStartedTutorial": "Začíname s návodom",
"ApplicationDevelopmentTutorial": "Návod Vývoj aplikácií",
"TheStartupTemplate": "Štartovacia šablóna",
"InstallABPCLIInfo": "ABP CLI je najrýchlejší spôsob, ako začať s novým riešením v ABP frameworku. Nainštalujte ABP CLI pomocou okna príkazového riadka:",
"DifferentLevelOfNamespaces": "Môžete použiť rôzne úrovne menných priestorov, napr. BookStore, Acme.BookStore alebo Acme.Retail.BookStore.",
"ABPCLIExamplesInfo": "Príkaz <strong>new</strong> vytvorí <strong>vrstvovú aplikáciu MVC</strong> s <strong>Entity Framework Core</strong> ako poskytovateľom databázy. Má však ďalšie možnosti. Príklady:",
"SeeCliDocumentForMoreInformation": "Viac možností nájdete v <a href=\"{0}\">dokumente CLIABP</a> alebo vyberte vyššie uvedenú kartu \"Priame stiahnutie\".",
"Optional": "Voliteľné",
"LocalFrameworkRef": "V rámci frameworkových balíkov dodržiavajte lokálne projektové referencie.",
"BlobStoring": "BLOB Storing",
"BlobStoringExplanation": "BLOB storing systém poskytuje abstrakciu na prácu s BLOBmi. ABP poskytuje niekoľko predpripravených integrácií poskytovateľov úložísk (Azure, AWS, File System, Database atď.), ktoré môžete jednoducho použiť vo svojich aplikáciách.",
"TextTemplating": "Šablónovanie textu",
"TextTemplatingExplanation": "Šablónovanie textu sa používa na dynamické vykresľovanie obsahu na základe šablóny a modelu (dátového objektu). Môžete ho napríklad použiť na vytvorenie dynamického obsahu e-mailu s vopred vytvorenou šablónou.",
"MultipleUIOptions": "Viacero možností používateľského rozhrania",
"MultipleDBOptions": "Viacerí poskytovatelia databáz",
"MultipleUIOptionsExplanation": "Framework core je navrhnuté ako nezávislé od používateľského rozhrania a môže pracovať s akýmkoľvek typom systému používateľského rozhrania, pričom je k dispozícii viacero predpripravených a integrovaných možností.",
"MultipleDBOptionsExplanation": "Framework môže pracovať s ľubovoľným zdrojom údajov, pričom oficiálne sú vyvinuté a podporované nasledujúce poskytovatelia;",
"SelectLanguage": "Výber jazyka",
"LatestArticleOnCommunity": "Najnovší článok v ABP komunite",
"Register": "Registrácia",
"IsDownloadable": "Je možné ho stiahnuť"
}
}

1
build/common.ps1

@ -7,6 +7,7 @@ $rootFolder = (Get-Item -Path "./" -Verbose).FullName
# List of solutions used only in development mode
$solutionPaths = @(
"../framework",
"../modules/basic-theme",
"../modules/users",
"../modules/permission-management",
"../modules/setting-management",

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>4.4.0</Version>
<Version>5.0.0</Version>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

3
docs/en/Best-Practices/Domain-Services.md

@ -1,3 +1,4 @@
## Domain Services Best Practices & Conventions
TODO
> **This document is not ready yet. Please see the [Domain Services](../Domain-Services.md) document.**

3
docs/en/Best-Practices/Index.md

@ -25,3 +25,6 @@ Also, this guide is mostly usable for general **application development**.
* [Entity Framework Core Integration](Entity-Framework-Core-Integration.md)
* [MongoDB Integration](MongoDB-Integration.md)
## See Also
* [E-Book: Implementing Domain Driven Design](https://abp.io/books/implementing-domain-driven-design)

174
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/POST.md

@ -0,0 +1,174 @@
# ABP Platform 4.4 RC Has Been Released
Today, we have released the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version 4.4 RC (Release Candidate). This blog post introduces the new features and important changes in this new version.
> **The planned release date for the [4.4.0 final](https://github.com/abpframework/abp/milestone/53) version is July 13, 2021**.
## Get Started with the 4.4 RC
If you want to try the version 4.4.0 today, follow the steps below;
1) **Upgrade** the ABP CLI to the version `4.4.0-rc.1` using a command line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 4.4.0-rc.1
````
**or install** if you haven't installed before:
````bash
dotnet tool install Volo.Abp.Cli -g --version 4.4.0-rc.1
````
2) Create a **new application** with the `--preview` option:
````bash
abp new BookStore --preview
````
See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options.
> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**.
### Migration Notes
There is **no breaking change** with this version. However, if you are using Entity Framework Core, you will need to run the `Add-Migration` command to add a new **database migration** since some changes done in the module database mappings.
## What's new with the ABP Framework 4.4
### Removed EntityFrameworkCore.DbMigrations Project
With this version, we are doing an important change in the application startup solution template. The startup solution was containing an `EntityFrameworkCore.DbMigrations` project that contains a separate `DbContext` class which was responsible to unify the module database mappings and maintain the code-first database migrations. With the v4.4, we've removed that project from the solution. In the new structure, the `EntityFrameworkCore` integration project will be used for database migrations as well as on runtime.
We'd published [a community article](https://community.abp.io/articles/unifying-dbcontexts-for-ef-core-removing-the-ef-core-migrations-project-nsyhrtna) about that change. Please see the article to understand the motivation behind the change.
Beside the `DbContext` unification, we've also used the new `ReplaceDbContext` attribute and [replaced](https://github.com/abpframework/abp/blob/ea2205f0855f52015152ae066a5c239af4b8511f/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContext.cs#L18-L19) the `IIdentityDbContext` and `ITenantManagementDbContext` interfaces to make it possible to perform join queries over repositories for these modules easily. In the next days, we will publish another community article to explain the problem and the solution. However, most of times, you don't need to know these details.
### Dynamic Menu Management for the CMS Kit Module
CMS Kit is a set of reusable *Content Management System* features packaged as an ABP application module. We had published the first usable version with the previous release. With this release, we are adding another feature to the CMS Kit module: You can now dynamically arrange the main menu on the UI, which is an essential feature for any kind of content management system. In this way, you can add pages or any kind of arbitrary URLs to the main menu from the UI.
A screenshot from the menu management page (from the CMS Kit admin side):
![menu-items-admin](menu-items-admin.png)
And the items rendered in a public website:
![menu-items-public](menu-items-public.png)
Note that this feature is also available with the open source [CMS Kit module](https://docs.abp.io/en/abp/4.4/Modules/Cms-Kit/Index) (while the screenshots have been taken from the ABP Commercial).
### Razor Engine Support for Text Templating
[Text Templating](https://docs.abp.io/en/abp/4.4/Text-Templating) is a system to generate content on runtime by using a model (data) and a template. It was running on the [Scriban](https://github.com/scriban/scriban) templating engine. Beginning from this version, we have a second option: We can use the familiar **razor syntax** to build and render the templates. See the text templating [razor integration document](https://docs.abp.io/en/abp/4.4/Text-Templating-Razor) to get started with the new engine!
### New Customization Points for DbContext/Entities
Two new extension methods are added to `ObjectExtensionManager.Instance` to override EF Core mappings of [pre-built application modules](https://docs.abp.io/en/abp/latest/Modules/Index).
**Example: Change mappings for the `IdentityDbContext` to override mappings for the `IdentityUser` entity**
````csharp
ObjectExtensionManager.Instance.MapEfCoreDbContext<IdentityDbContext>(modelBuilder =>
{
modelBuilder.Entity<IdentityUser>(b =>
{
b.ToTable("MyUsers");
b.Property(x => x.Email).HasMaxLength(300);
});
});
````
The startup template contains a class, like `YourProjectNameEfCoreEntityExtensionMappings`, that can be used to place that code.
### New ABP CLI Commands
There are new [ABP CLI](https://docs.abp.io/en/abp/4.4/CLI) commands introduced with the v4.4:
* `abp install-libs` command is used for MVC / Razor Pages and Blazor Server applications to restore the `wwwroot/libs` folder. Previously we were running the `yarn` and `gulp` commands to restore that folder. While the `install-libs` command still uses yarn (if available), it is no longer needed to use `gulp`.
* `abp prompt` command can be used to open a prompt for the ABP CLI and run multiple commands without needing to specify the `abp` command every time. For example, if you run `abp prompt`, then you can directly run `install-libs` instead of `abp install-libs`. Use `exit` to quit from the ABP prompt.
* `abp batch` command can be used to run multiple ABP commands with one command. Prepare a text file, write each command as a line (without the `abp` command prefix), then execute `abp batch <batch-file>` (ex: `abp batch your_commands.txt`) command to execute all the commands in that file.
### appsettings.secrets.json
Added `appsettings.secrets.json` to the startup template that can be used to set your sensitive/secret configuration values. You can ignore this file from source control (by adding to `.gitignore` if you're using git) and keep it only in developer/production machines.
### Other ABP Framework Improvements
* [#9350](https://github.com/abpframework/abp/pull/9350) Extracted `IRemoteServiceConfigurationProvider` to get remote service configurations. You can replace this service to get the configuration from any source.
* [#8829](https://github.com/abpframework/abp/pull/8829) Implemented error handler and retry for distributed event bus.
* [#9288](https://github.com/abpframework/abp/issues/9288) Use default CORS policy instead of a named one in the startup template. It is suggested to update your own solutions to make it simpler.
* Translated the framework and module localization strings to Hindi, Italian, Finnish and French languages.
Beside these, there are a lot of enhancements and bug fixes. See the [4.4-preview milestone](https://github.com/abpframework/abp/milestone/52?closed=1) for all issues and pull requests closed with this version.
## What's new with the ABP Commercial 4.4
### New Features for the SaaS Module
We've implemented some important features to the [SaaS module](https://commercial.abp.io/modules/Volo.Saas):
* Integrated to the [Payment module](https://commercial.abp.io/modules/Volo.Payment) and implemented **subscription system** for the SaaS module.
* Allow to make a **tenant active/passive**. In this way, you can take a tenant to passive to prevent the users of that tenant from using the system. In addition, you can set a date to automatically make a tenant passive when the date comes.
* Allow to **limit user count** for a tenant.
* Allow to set **different connection strings** for a tenant for each database/module, which makes possible to create different databases for a tenant for each microservice in a microservice solution.
### New ABP Suite Code Generation Features
There are many improvements done for for [ABP Suite](https://commercial.abp.io/tools/suite), including CRUD page generation for the **[microservice solution](https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index) template**.
### Angular UI: Two Factor Authentication for the Resource Owner Password Flow
In the previous version, we had implemented the resource owner password authentication flow for the Angular UI, which makes the login process easier for simpler applications. With this release, we've implemented two-factor authentication for that flow. Authorization code flow already supports 2FA.
### Other ABP Commercial Improvements
* Added web layers to microservices in the microservice solution. You can use them to create modular UI or override existing pages/components of pre-built modules (e.g. Identity and SaaS).
* ABP Commercial license code has been moved to `appsettings.secrets.json` in the new startup templates.
* Added new language options: Hindi, Italian, Arabic, Finnish, French.
Beside these, there are many minor improvements and fixes done in the modules and themes.
## Other News
In this section, I will share some news that you may be interested in.
### New Article: Using Elsa Workflow with ABP Framework
We have been frequently asked how to use [Elsa Workflows](https://elsa-workflows.github.io/elsa-core/) with the ABP Framework. Finally, we have [created an article](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to demonstrate it.
![elsa-overview](elsa-overview.gif)
You can [check it](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to see how to integrate Elsa into an ABP based solution easily.
### Free E-Book: Implementing Domain Driven Design
We've published a free e-book for the ABP Community in the beginning of June. This is a practical guide for implementing Domain Driven Design (DDD). While the implementation details are based on the ABP Framework infrastructure, the basic concepts, principles and models can be applied to any solution, even if it is not a .NET solution.
![ddd-book](ddd-book.png)
Thousands of copies are already downloaded. If you haven't seen it yet, [click here to get a free copy of that e-book](https://abp.io/books/implementing-domain-driven-design).
### The LeptonX Theme
We have been working on a new ABP theme, named the *LeptonX*, for a long time. The theme will be available for ABP Framework (free - lite version) and ABP Commercial (pro version). It is being finalized in the next weeks and we will release the first version in a short time.
![leptonx](leptonx.png)
See [this blog post](https://volosoft.com/blog/introducing-the-lepton-theme-next-generation) to learn more about that project.
### Volosoft & .NET Foundation
[Volosoft](https://volosoft.com/), the company leads the ABP Framework project, has been a corporate sponsor of the [.NET Foundation](https://dotnetfoundation.org/). We are happy by taking our place among other great sponsors!
![dotnetfoundation-sponsor-volosoft](dotnetfoundation-sponsor-volosoft.png)
We will continue to contribute to and support open source! See this [blog post for the announcement](https://volosoft.com/blog/Volosoft-Announces-the-NET-Foundation-Sponsorship).
### Looking for Developer Advocate(s)
We are actively looking for professional developer advocates for the ABP.IO platform. If you want to create content and touch to the ABP community, please check our [job post](https://github.com/volosoft/vs-home/issues/13).
## About the Next Version
The next version will be a major version: 5.0, which will be based on .NET 6.0. We are planning to release it in the end of 2021, short time after the .NET 6.0 release. We will release multiple preview/beta versions before the RC version. See the [road map](https://docs.abp.io/en/abp/latest/Road-Map) for details of the planned works for the version 5.0.

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/abp-44-cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/ddd-book.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/dotnetfoundation-sponsor-volosoft.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/elsa-overview.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/leptonx.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-admin.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-public.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

52
docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/POST.md

@ -0,0 +1,52 @@
# Introducing the eShopOnAbp Project
We are happy to introduce the **eShopOnAbp** project as an example microservice solution built with the ABP Framework by the core ABP team. This solution demonstrates the strength of ABP Framework and using it in a real-life case. The goal of the project is to create a full-featured cloud-native microservices reference application. The project is inspired by the [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) project and shows how it can be implemented with the ABP Framework.
> **Project Status**: Currently, the project doesn't have any business logic. We've just brought ABP's pre-built modules (Identity, Tenant Management, IdentityServer, etc) together as a base solution. However, it is fully working and you can now take it as a base solution for your microservice project. From now on, we will build the example application functionalities / business logic on top of it.
## Source Code
The source code is available on [abpframework/eShopOnAbp](https://github.com/abpframework/eShopOnAbp) repository.
## The Big Picture
The project follows micro-service architecture and overall structure is presented below.
![eShopOnAbp Overall Solution](overall-solution.png)
## How to Run?
You can either run in Visual Studio, or using [Microsoft Tye](https://github.com/dotnet/tye). Tye is a developer tool that makes developing, testing, and deploying micro-services and distributed applications easier.
### Requirements
- .NET 5.0+
- Docker
- Yarn
### Instructions
- Clone the repository ( [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) )
- Install Tye (*follow [these steps](https://github.com/dotnet/tye/blob/main/docs/getting_started.md#installing-tye)*)
- Execute `run-tye.ps1`
- Wait until all applications are up!
- You can check running application from tye dashboard ([localhost:8000](http://127.0.0.1:8000/))
- After all your backend services are up, start the angular application:
```bash
cd apps/angular
yarn start
```
## What's Next?
We'll work on deployment & CI-CD processes as a next step and build the business logic on. First goal is deploying the entire application on [Kubernetes](https://kubernetes.io/).
## Feedback
Your comments and suggestions is important for us. You can ask your questions or post your feedback under [this discussion entry](https://github.com/abpframework/abp/discussions/9536).

BIN
docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/overall-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

8
docs/en/CLI-New-Command-Samples.md

@ -1,6 +1,6 @@
# ABP CLI Create Solution Sample Commands
The `abp new` command creates an ABP solution or other artifacts based on an ABP template. ABP CLI has several parameters to create a new ABP solution. In this document we will show you some sample commands to create a new solution. All the project names are `Acme.BookStore`. Currently, the only available mobile project is a `React Native` mobile app. Available database providers are `Entity Framework Core` and `MongoDB`. All the commands starts with `abp new`.
The `abp new` command creates an ABP solution or other artifacts based on an ABP template. [ABP CLI](CLI.md) has several parameters to create a new ABP solution. In this document we will show you some sample commands to create a new solution. All the project names are `Acme.BookStore`. Currently, the only available mobile project is a `React Native` mobile app. Available database providers are `Entity Framework Core` and `MongoDB`. All the commands starts with `abp new`.
## Angular
@ -217,6 +217,10 @@ As seen below, ABP Framework libraries are local project references.
<ProjectReference Include="C:\source\abp\framework\src\Volo.Abp.AspNetCore.Authentication.JwtBearer\Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj" />
<ProjectReference Include="..\Acme.BookStore.Application\Acme.BookStore.Application.csproj" />
<ProjectReference Include="..\Acme.BookStore.HttpApi\Acme.BookStore.HttpApi.csproj" />
<ProjectReference Include="..\Acme.BookStore.EntityFrameworkCore.DbMigrations\Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj" />
<ProjectReference Include="..\Acme.BookStore.EntityFrameworkCore\Acme.BookStore.EntityFrameworkCore.csproj" />
</ItemGroup>
```
## See Also
* [ABP CLI documentation](CLI.md)

8
docs/en/CLI.md

@ -119,6 +119,8 @@ For more samples, go to [ABP CLI Create Solution Samples](CLI-New-Command-Sample
* `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application.
* `--no-random-port`: Uses template's default ports.
See some [examples for the new command](CLI-New-Command-Samples.md) here.
### update
Updating all ABP related packages can be tedious since there are many packages of the framework and modules. This command automatically updates all ABP related NuGet and NPM packages in a solution or project to the latest versions.
@ -448,4 +450,8 @@ abp install-libs [options]
#### Options
* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a project file.
* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a project file.
## See Also
* [Examples for the new command](CLI-New-Command-Samples.md)

4
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md

@ -101,7 +101,7 @@ Now we need to add migration to see what has changed in our database. This for,
![nuget-package-manager](./nuget-package-manager.png)
Select the **CustomizeUserDemo.EntityFramework.DbMigrations** as the **default project** and execute the following command:
Select the **CustomizeUserDemo.EntityFramework** as the **default project** and execute the following command:
```bash
Add-Migration "Updated-User-Entity"
@ -109,7 +109,7 @@ Add-Migration "Updated-User-Entity"
![added-new-migration](./added-new-migration.png)
This will create a new migration class inside the `Migrations` folder of the **CustomizeUserDemo.EntityFrameworkCore.DbMigrations** project.
This will create a new migration class inside the `Migrations` folder of the **CustomizeUserDemo.EntityFrameworkCore** project.
> If you are using another IDE than the Visual Studio, you can use `dotnet-ef` tool as [documented here](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli#create-a-migration).

BIN
docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 11 KiB

2
docs/en/Connection-Strings.md

@ -70,7 +70,7 @@ For [Entity Framework Core](Entity-Framework-Core.md) and [MongoDB](MongoDB.md),
Relational databases require to create the database and the database schema (tables, views... etc.) before using it.
The startup template (with EF Core ORM) comes with a single database and a `.EntityFrameworkCore.DbMigrations` project that contains the migration files for that database. This project mainly defines a *YourProjectName*MigrationsDbContext that calls the `Configure...()` methods of the used modules, like `builder.ConfigurePermissionManagement()`.
The startup template (with EF Core ORM) comes with a single database and a `.EntityFrameworkCore` project that contains related classes and the migration files for that database. This project mainly defines a *YourProjectName*DbContext that calls the `Configure...()` methods of the used modules, like `builder.ConfigurePermissionManagement()`.
Once you want to separate a module's database, you typically will need to create a second migration path. See the [EF Core Migrations](Entity-Framework-Core-Migrations.md) document to learn how to create and use a different database for a desired module.

6
docs/en/Customizing-Application-Modules-Extending-Entities.md

@ -152,14 +152,14 @@ public class MyDistributedIdentityUserChangeEventHandler :
* It implements multiple `IDistributedEventHandler` interfaces: **Created**, **Updated** and **Deleted**. Because, the distributed event bus system publishes events individually. There is no "Changed" event like the local event bus.
* It subscribes to `EntityEto`, which is a generic event class that is **automatically published** for all type of entities by the ABP framework. This is why it checks the **entity type** (checking the entity type as string since we assume that there is no type safe reference to the `IdentityUser` entity).
Pre-built application modules do not define specialized event types yet (like `IdentityUserEto` - "ETO" means "Event Transfer Object"). This feature is on the road map and will be available in a short term ([follow this issue](https://github.com/abpframework/abp/issues/3033)). Once it is implemented, you will be able to subscribe to individual entity types. Example:
Pre-built application modules do not define specialized event types yet (like `UserEto` - "ETO" means "Event Transfer Object"). This feature is on the road map and will be available in a short term ([follow this issue](https://github.com/abpframework/abp/issues/3033)). Once it is implemented, you will be able to subscribe to individual entity types. Example:
````csharp
public class MyDistributedIdentityUserCreatedEventHandler :
IDistributedEventHandler<EntityCreatedEto<IdentityUserEto>>,
IDistributedEventHandler<EntityCreatedEto<UserEto>>,
ITransientDependency
{
public async Task HandleEventAsync(EntityCreatedEto<IdentityUserEto> eventData)
public async Task HandleEventAsync(EntityCreatedEto<UserEto> eventData)
{
var userId = eventData.Entity.Id;
var userName = eventData.Entity.UserName;

53
docs/en/Distributed-Event-Bus.md

@ -4,7 +4,7 @@ Distributed Event bus system allows to **publish** and **subscribe** to events t
## Providers
Distributed event bus system provides an **abstraction** that can be implemented by any vendor/provider. There are two providers implemented out of the box:
Distributed event bus system provides an **abstraction** that can be implemented by any vendor/provider. There are four providers implemented out of the box:
* `LocalDistributedEventBus` is the default implementation that implements the distributed event bus to work as in-process. Yes! The **default implementation works just like the [local event bus](Local-Event-Bus.md)**, if you don't configure a real distributed provider.
* `RabbitMqDistributedEventBus` implements the distributed event bus with the [RabbitMQ](https://www.rabbitmq.com/). See the [RabbitMQ integration document](Distributed-Event-Bus-RabbitMQ-Integration.md) to learn how to configure it.
@ -302,3 +302,54 @@ namespace AbpDemo
````
This example uses the `AutoMap` attribute of the AutoMapper to configure the mapping. You could create a profile class instead. Please refer to the AutoMapper document for more options.
## Exception Handling
ABP provides exception handling and retries when an exception occurs, it will move to the dead letter queue after the retry fails.
Enable exception handling:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.EnabledErrorHandle = true;
options.UseRetryStrategy();
});
}
```
* `EnabledErrorHandle` is used to enable exception handing.
* `UseRetryStrategy` is used to enable retry.
When an exception occurs, it will retry every three seconds up to the maximum number of retries(default is 3) and move to dead letter queue, you can change the number of retries, retry interval and dead letter queue name:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.DeadLetterName = "dead_queue";
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### Error Handle Selector
By default all event types will be exception handling, you can use `ErrorHandleSelector` of `AbpEventBusOptions` to change it:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` actually a list of type predicate. You can write a lambda expression to define your filter.
### Customize Exception Handling
ABP defines the `IEventErrorHandler` interface and implemented by the provider, you can replace it via [dependency injection](Dependency-Injection.md)

834
docs/en/Entity-Framework-Core-Migrations.md

@ -61,9 +61,9 @@ ABP Framework's [connection string](Connection-Strings.md) system allows you to
}
````
The example configuration about tells to the ABP Framework to use the second connection string for the [Audit Logging module](Modules/Audit-Logging.md).
The example configuration tells to the ABP Framework to use the second connection string for the [Audit Logging module](Modules/Audit-Logging.md) (if you don't specify connection string for a module, it uses the `Default` connection string).
**However, this is just the beginning**. You also need to create the second database, create audit log tables inside it and maintain the database tables using the code first migrations approach. One of the main purposes of this document is to guide you on such **database separation** scenarios.
**However, this can work only if the audit log database with the given connection string is available**. So, you need to create the second database, create audit log tables inside it and maintain the database tables. No problem if you manually do all these. However, the recommended approach is the code first migrations. One of the main purposes of this document is to guide you on such **database separation** scenarios.
#### Module Tables
@ -85,23 +85,24 @@ This code changes the prefix of the [Identity Server](Modules/IdentityServer.md)
> Every module also defines `DbSchema` property (near to `DbTablePrefix`), so you can set it for the databases support the schema usage.
### The Projects
### .EntityFrameworkCore Project
From the database point of view, there are three important projects those will be explained in the next sections.
The solution contains a project, which's name ends with `.EntityFrameworkCore`. This project has the `DbContext` class (`BookStoreDbContext` for this sample) of your application.
#### .EntityFrameworkCore Project
This project has the `DbContext` class (`BookStoreDbContext` for this sample) of your application.
**Every module uses its own `DbContext` class** to access to the database. Likewise, your application has its own `DbContext`. You typically use this `DbContext` in your application code (in your [repositories](Repositories.md) if you follow the best practices). It is almost an empty `DbContext` since your application don't have any entities at the beginning, except the pre-defined `AppUser` entity:
**Every module uses its own `DbContext` class** to access to the database. Likewise, your application has its own `DbContext`. You typically use this `DbContext` in your application code (in your [repositories](Repositories.md) if you follow the best practices and hide your data access code behind the repositories). It is almost an empty `DbContext` since your application don't have any entities at the beginning:
````csharp
[ReplaceDbContext(typeof(IIdentityDbContext))]
[ReplaceDbContext(typeof(ITenantManagementDbContext))]
[ConnectionStringName("Default")]
public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
public class BookStoreDbContext :
AbpDbContext<BookStoreDbContext>,
IIdentityDbContext,
ITenantManagementDbContext
{
public DbSet<AppUser> Users { get; set; }
/* Add DbSet properties for your Aggregate Roots / Entities here. */
/* DbSet for entities from the replaced DbContexts */
public BookStoreDbContext(DbContextOptions<BookStoreDbContext> options)
: base(options)
@ -112,72 +113,7 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Configure the shared tables (with included modules) here */
builder.Entity<AppUser>(b =>
{
//Sharing the same Users table with the IdentityUser
b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Users");
b.ConfigureByConvention();
b.ConfigureAbpUser();
/* Configure mappings for your additional properties
* Also see the MyProjectNameEntityExtensions class
*/
});
/* Configure your own tables/entities inside the ConfigureBookStore method */
builder.ConfigureBookStore();
}
}
````
This simple `DbContext` class still needs some explanations:
* It defines a `[ConnectionStringName]` attribute which tells ABP to always use the `Default` connection string for this `Dbcontext`.
* It inherits from the `AbpDbContext<T>` instead of the standard `DbContext` class. You can see the [EF Core integration](Entity-Framework-Core.md) document for more. For now, know that the `AbpDbContext<T>` base class implements some conventions of the ABP Framework to automate some common tasks for you.
* It declares a `DbSet` property for the `AppUser` entity. `AppUser` shares the same table (named `AbpUsers` by default) with the `IdentityUser` entity of the [Identity module](Modules/Identity.md). The startup template provides this entity inside the application since we think that the User entity is generally needs to be customized in your application.
* The constructor takes a `DbContextOptions<T>` instance.
* It overrides the `OnModelCreating` method to define the EF Core mappings.
* It first calls the the `base.OnModelCreating` method to let the ABP Framework to implement the base mappings for us.
* It then configures the mapping for the `AppUser` entity. There is a special case for this entity (it shares a table with the Identity module), which will be explained in the next sections.
* It finally calls the `builder.ConfigureBookStore()` extension method to configure other entities of your application.
This design will be explained in more details after introducing the other database related projects.
#### .EntityFrameworkCore.DbMigrations Project
As mentioned in the previous section, every module (and your application) have **their own** separate `DbContext` classes. Each `DbContext` class only defines the entity to table mappings related to its own module and each module (and your application) use the related `DbContext` class **on runtime**.
As you know, EF Core Code First migration system relies on a `DbContext` class **to track and generate** the code first migrations. So, which `DbContext` we should use for the migrations? The answer is *none of them*. There is another `DbContext` defined in the `.EntityFrameworkCore.DbMigrations` project (which is the `BookStoreMigrationsDbContext` for this example solution).
##### The MigrationsDbContext
The `MigrationsDbContext` is only used to create and apply the database migrations. It is **not used on runtime**. It **merges** all the entity to table mappings of all the used modules plus the application's mappings.
In this way, you create and maintain a **single database migration path**. However, there are some difficulties of this approach and the next sections explains how ABP Framework overcomes these difficulties. But first, see the `BookStoreMigrationsDbContext` class as an example:
````csharp
/* This DbContext is only used for database migrations.
* It is not used on runtime. See BookStoreDbContext for the runtime DbContext.
* It is a unified model that includes configuration for
* all used modules and your application.
*/
public class BookStoreMigrationsDbContext : AbpDbContext<BookStoreMigrationsDbContext>
{
public BookStoreMigrationsDbContext(
DbContextOptions<BookStoreMigrationsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
@ -188,391 +124,42 @@ public class BookStoreMigrationsDbContext : AbpDbContext<BookStoreMigrationsDbCo
builder.ConfigureFeatureManagement();
builder.ConfigureTenantManagement();
/* Configure your own tables/entities inside the ConfigureBookStore method */
builder.ConfigureBookStore();
}
}
````
##### Sharing the Mapping Code
First problem is that: A module uses its own `DbContext` which needs to the database mappings. The `MigrationsDbContext` also needs to the same mapping in order to create the database tables for this module. We definitely **don't want to duplicate** the mapping code.
The solution is to define an **extension method** (on the `ModelBuilder`) that can be called by both `DbContext` classes. So, all modules define such extension methods.
For example, the `builder.ConfigureBackgroundJobs()` method call configures the database tables for the [Background Jobs module](Modules/Background-Jobs.md). The definition of this extension method is something like that:
````csharp
public static class BackgroundJobsDbContextModelCreatingExtensions
{
public static void ConfigureBackgroundJobs(
this ModelBuilder builder,
Action<BackgroundJobsModelBuilderConfigurationOptions> optionsAction = null)
{
var options = new BackgroundJobsModelBuilderConfigurationOptions(
BackgroundJobsDbProperties.DbTablePrefix,
BackgroundJobsDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<BackgroundJobRecord>(b =>
{
b.ToTable(options.TablePrefix + "BackgroundJobs", options.Schema);
b.ConfigureCreationTime();
b.ConfigureExtraProperties();
b.Property(x => x.JobName)
.IsRequired()
.HasMaxLength(BackgroundJobRecordConsts.MaxJobNameLength);
//...
});
/* Configure your own tables/entities here. Example: */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable("YourEntities");
// b.ConfigureByConvention(); //auto configure for the base properties
// //...
//});
}
}
````
This extension method also gets options to change the database table prefix and schema for this module, but it is not important here.
The final application calls the extension methods inside the `MigrationsDbContext` class, so it can decide which modules are included in the database maintained by this `MigrationsDbContext`. If you want to create a second database and move some module tables to the second database, then you need to have a second `MigrationsDbContext` class which only calls the extension methods of the related modules. This topic will be detailed in the next sections.
The same `ConfigureBackgroundJobs` method is also called in the `DbContext` of the Background Jobs module:
````csharp
[ConnectionStringName(BackgroundJobsDbProperties.ConnectionStringName)]
public class BackgroundJobsDbContext
: AbpDbContext<BackgroundJobsDbContext>, IBackgroundJobsDbContext
{
public DbSet<BackgroundJobRecord> BackgroundJobs { get; set; }
public BackgroundJobsDbContext(DbContextOptions<BackgroundJobsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
//Reuse the same extension method!
builder.ConfigureBackgroundJobs();
}
}
````
In this way, the mapping configuration of a module can be shared between `DbContext` classes. The code above is inside the related module NuGet package, so you don't care about it.
##### Reusing a Table of a Module
You may want to **reuse a table** of a depended module in your application. In this case, you have two options:
1. You can **directly use the entity** defined by the module (you can still [extend the entity](Customizing-Application-Modules-Extending-Entities.md) in some level).
2. You can **create a new entity** mapping to the same database table.
###### Use the Entity Defined by a Module
Using an entity defined a module is pretty easy and standard. For example, Identity module defines the `IdentityUser` entity. You can inject the [repository](Repositories.md) for the `IdentityUser` and perform the standard repository operations for this entity. Example:
````csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
namespace Acme.BookStore
{
public class MyService : ITransientDependency
{
private readonly IRepository<IdentityUser, Guid> _identityUserRepository;
public MyService(IRepository<IdentityUser, Guid> identityUserRepository)
{
_identityUserRepository = identityUserRepository;
}
public async Task DoItAsync()
{
//Get all users
var users = await _identityUserRepository.GetListAsync();
}
}
}
````
This example injects the `IRepository<IdentityUser, Guid>` (default repository) which defines the standard repository methods and implements the `IQueryable` interface.
> In addition, Identity module defines the `IIdentityUserRepository` (custom repository) that can also be injected and used by your application. `IIdentityUserRepository` provides additional custom methods for the `IdentityUser` entity while it does not implement the `IQueryable` interface.
###### Create a New Entity
Working with an entity of a module is easy if you want to use the entity as is. However, you may want to define your own entity class and map to the same database table in the following cases;
* You want to **add a new field** to the table and map it to a property in the entity. You can't use the module's entity since it doesn't have the related property.
* You want to **use a subset of the table fields**. You don't want to access to all properties of the entity and hide the unrelated properties (from a security perspective or just by design).
* You don't want to directly **depend on** a module entity class.
In any case, the progress is same. Assume that you want to create an entity, named `AppRole`, mapped to the same table of the `IdentityRole` entity of the [Identity module](Modules/Identity.md).
Here, we will show the implementation, then **will discuss the limitations** of this approach.
First, create a new `AppRole` class in your `.Domain` project:
````csharp
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Acme.BookStore.Roles
{
public class AppRole : AggregateRoot<Guid>, IMultiTenant
{
// Properties shared with the IdentityRole class
public Guid? TenantId { get; private set; }
public string Name { get; private set; }
//Additional properties
public string Title { get; set; }
private AppRole()
{
}
}
}
````
* It's inherited from [the `AggregateRoot<Guid>` class](Entities.md) and implements [the `IMultiTenant` interface](Multi-Tenancy.md) because the `IdentityRole` also does the same.
* You can add any properties defined by the `IdentityRole` entity. This examples add only the `TenantId` and `Name` properties since we only need them here. You can make the setters private (like in this example) to prevent changing Identity module's properties accidently.
* You can add custom (additional) properties. This example adds the `Title` property.
* The **constructor is private**, so it is not allowed to directly create a new `AppRole` entity. Creating a role is a responsibility of the Identity module. You can query roles, set/update your custom properties, but you should not create or delete a role in your code, as a best practice (while there is nothing restricts you).
Now, it is time to define the EF Core mappings. Open the `DbContext` of your application (`BookStoreDbContext` in this sample) and add the following property:
````csharp
public DbSet<AppRole> Roles { get; set; }
````
Then configure the mapping inside the `OnModelCreating` method (after calling the `base.OnModelCreating(builder)`):
````csharp
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Configure the shared tables (with included modules) here */
//CONFIGURE THE AppRole ENTITY
builder.Entity<AppRole>(b =>
{
b.ToTable("AbpRoles");
b.ConfigureByConvention();
b.Property(x => x.Title).HasMaxLength(128);
});
...
/* Configure your own tables/entities inside the ConfigureBookStore method */
builder.ConfigureBookStore();
}
````
We added the following lines:
````csharp
builder.Entity<AppRole>(b =>
{
b.ToTable("AbpRoles");
b.ConfigureByConvention();
b.Property(x => x.Title).HasMaxLength(128);
});
````
* It maps to the same `AbpRoles` table shared with the `IdentityRole` entity.
* `ConfigureByConvention()` configures the standard/base properties (like `TenantId`) and recommended to always call it.
You've configured the custom property for your `DbContext` that is used by your application on the runtime. We also need to configure the `MigrationsDbContext`.
Instead of directly changing the `MigrationsDbContext`, we **should** use the entity extension system of the ABP Framework. Find the `YourProjectNameEfCoreEntityExtensionMappings` class in the `.EntityFrameworkCore` project of your solution (`BookStoreEfCoreEntityExtensionMappings` for this example) and change it as shown below:
````csharp
public static class MyProjectNameEntityExtensions
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityRole, string>(
"Title",
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.HasMaxLength(128);
}
);
});
}
}
````
This `DbContext` class needs some explanations:
> Instead of hard-coded "Title" string, we suggest to use `nameof(AppRole.Title)` or use a constant string.
`ObjectExtensionManager` is used to add properties to existing entities. Since `ObjectExtensionManager.Instance` is a static instance (singleton), we should call it once. `OneTimeRunner` is a simple utility class defined by the ABP Framework.
See the [EF Core integration documentation](Entity-Framework-Core.md) for more about the entity extension system.
> We've repeated a similar database mapping code, like `HasMaxLength(128)`, in both classes.
Now, you can add a new EF Core database migration using the standard `Add-Migration` command in the Package Manager Console (remember to select `.EntityFrameworkCore.DbMigrations` as the Default Project in the PMC and make sure that the `.Web` project is still the startup project):
![pmc-add-migration-role-title](images/pmc-add-migration-role-title.png)
This command will create a new code first migration class as shown below:
````csharp
public partial class Added_Title_To_Roles : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Title",
table: "AbpRoles",
maxLength: 128,
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Title",
table: "AbpRoles");
}
}
````
All done! Just run the `Update-Database` command in the PMC or run the `.DbMigrator` project in your solution to apply changes to database.
Now, you can work with the `AppRole` entity just like any other entity of your application. An example [application service](Application-Services.md) that queries and updates roles:
````csharp
public class AppRoleAppService : ApplicationService, IAppRoleAppService
{
private readonly IRepository<AppRole, Guid> _appRoleRepository;
public AppRoleAppService(IRepository<AppRole, Guid> appRoleRepository)
{
_appRoleRepository = appRoleRepository;
}
public async Task<List<AppRoleDto>> GetListAsync()
{
var roles = await _appRoleRepository.GetListAsync();
return roles
.Select(r => new AppRoleDto
{
Id = r.Id,
Name = r.Name,
Title = r.Title
})
.ToList();
}
public async Task UpdateTitleAsync(Guid id, string title)
{
var role = await _appRoleRepository.GetAsync(id);
role.Title = title;
await _appRoleRepository.UpdateAsync(role);
}
}
````
There are some **limitations** of creating a new entity and mapping it to a table of a depended module:
* Your **custom properties must be nullable**. For example, `AppRole.Title` was nullable here. Otherwise, Identity module throws exception because it doesn't know and can not fill the Title when it inserts a new role to the database.
* As a good practice, you should not update the **properties defined by the module**, especially if it requires a business logic. You typically want to manage your own properties.
##### Alternative Approaches
Instead of creating a new entity class to add a custom property, you can use the following approaches.
###### Using the ExtraProperties
All entities derived from the `AggregateRoot ` class can store name-value pairs in their `ExtraProperties` property (because they implement the `IHasExtraProperties` interface), which is a `Dictionary<string, object>` serialized to JSON in the database table. So, you can add values to this dictionary and query again without changing the entity.
For example, you can store query the title Property inside an `IdentityRole` instead of creating a new entity. Example:
````csharp
public class IdentityRoleExtendingService : ITransientDependency
{
private readonly IIdentityRoleRepository _identityRoleRepository;
public IdentityRoleExtendingService(IIdentityRoleRepository identityRoleRepository)
{
_identityRoleRepository = identityRoleRepository;
}
public async Task<string> GetTitleAsync(Guid id)
{
var role = await _identityRoleRepository.GetAsync(id);
return role.GetProperty<string>("Title");
}
public async Task SetTitleAsync(Guid id, string newTitle)
{
var role = await _identityRoleRepository.GetAsync(id);
role.SetProperty("Title", newTitle);
await _identityRoleRepository.UpdateAsync(role);
}
}
````
* `GetProperty` and `SetProperty` methods are shortcuts to get and set a value in the `role.ExtraProperties` dictionary and they are the recommended way to work with the extra properties.
In this way, you can easily attach any type of value to an entity of a depended module. However, there are some drawbacks of this usage:
* All the extra properties are stored as **a single JSON object** in the database. They are not stored as new table fields, as you may expect. Creating database table indexes and using SQL queries against these properties will be harder compared to simple table fields.
* Property names are strings, so they are **not type safe**. It is recommended to define constants for these kind of properties to prevent typo errors.
###### Using the Entity Extensions System
Entity extension system solves the main problem of the extra properties: It can store an extra property in a **standard table field** in the database.
All you need to do is to use the `ObjectExtensionManager` to define the extra property as explained above, in the `AppRole` example. Then you can continue to use the same `GetProperty` and `SetProperty` methods defined above to get/set the related property on the entity, but this time stored as a separate field in the database.
See the [entity extension system](Customizing-Application-Modules-Extending-Entities.md) for details.
###### Creating a New Table
Instead of creating a new entity and mapping to the same table, you can also create **your own table** to store your properties. You typically duplicate some values of the original entity. For example, you can add `Name` field to your own table which is a duplication of the `Name` field in the original table.
In this case, you don't deal with migration problems, however you need to deal with the problems of data duplication. When the duplicated value changes, you should reflect the same change in your table. You can use local or distributed [event bus](Event-Bus.md) to subscribe to the change events for the original entity. This is the recommended way of depending on a microservice's data from another microservice, especially if they have separate physical databases (you can search on the web on data sharing on a microservice design, it is a wide topic to cover here).
> See the "[extending entities](Customizing-Application-Modules-Extending-Entities.md)" guide for more details on extending entities, including data duplication and synchronization tips.
* It defines `[ReplaceDbContext]` attributes for `IIdentityDbContext` and `ITenantManagementDbContext` those replaces Identity and Tenant Management module's `DbContext`s by your `DbContext` on runtime. This allows us to easily perform LINQ queries by joining your entities with the entities (over the repositories) coming from those modules.
* It defines a `[ConnectionStringName]` attribute which tells ABP to always use the `Default` connection string for this `Dbcontext`.
* It inherits from the `AbpDbContext<T>` instead of the standard `DbContext` class. You can see the [EF Core integration](Entity-Framework-Core.md) document for more. For now, know that the `AbpDbContext<T>` base class implements some conventions of the ABP Framework to automate some common tasks for you.
* It declares `DbSet` properties for entities from the replaced `DbContext`s (by implementing the corresponding interfaces). These `DbSet` properties are not shown above (for the sake of brevity), but you can find in your application's code in a `region`.
* The constructor takes a `DbContextOptions<T>` instance.
* It overrides the `OnModelCreating` method to define the EF Core mappings.
* It first calls the the `base.OnModelCreating` method to let the ABP Framework to implement the base mappings for us.
* It then calls some `builder.ConfigureXXX()` methods for the used modules. This makes possible to add database mappings for these modules to this `DbContext`, so it creates the database tables of the modules when we add a new EF Core database migration.
* You can configure the mappings for your own entities as commented in the example code. At this point, you can also change mappings for the modules you are using.
#### Discussion of an Alternative Scenario: Every Module Manages Its Own Migration Path
### Discussion of an Alternative Scenario: Every Module Manages Its Own Migration Path
As mentioned before, `.EntityFrameworkCore.DbMigrations` merges all the database mappings of all the modules (plus your application's mappings) to create a unified migration path.
As mentioned before, in the `.EntityFrameworkCore` project, we merge all the database mappings of all the modules (plus your application's mappings) to create a unified migration path.
An alternative approach would be to allow each module to have its own migrations to maintain its database tables. While it seems more module in the beginning, it has some important drawbacks:
An alternative approach would be to allow each module to have its own migrations to maintain its database tables. While it seems more modular in the beginning, it has some drawbacks in practical:
* **EF Core migration system depends on the DBMS provider**. For example, if a module has created migrations for SQL Server, then you can not use this migration code for MySQL. It is not practical for a module to maintain migrations for all available DBMS providers. Leaving the migration to the application code (as explained in this document) allows you to **choose the DBMS in the application** code.
* It would be harder or impossible to **share a table** between modules or **re-use a table** of a module in your application. Because EF Core migration system can not handle it and will throw exceptions like "Table XXX is already exists in the database".
* It would be harder to **customize/enhance** the mapping and the resulting migration code.
* **EF Core migration system depends on the DBMS provider**. For example, if a module has created migrations for SQL Server, then you can not use this migration code for MySQL. It is not practical for a module to maintain migrations for all available DBMS providers. Leaving the migration to the application code (as explained in this document) allows you to **choose the DBMS in the application** code. If you can depend on a specific DBMS in your module, that's not an issue for you, however all pre-built ABP modules are DBMS agnostic.
* It would be harder to **customize/enhance** the mapping and the resulting migration code, in the final application.
* It would be harder to track and **apply changes** to database when you use multiple modules.
## Using Multiple Databases
The default startup template is organized to use a single database used by all the modules and by your application. However, the ABP Framework and all the pre-built modules are designed so that **they can use multiple databases**. Each module can use its own database or you can group modules into a few databases.
The default startup template is organized to use a **single database** used by all the modules and by your application. However, the ABP Framework and all the pre-built modules are designed so that **they can use multiple databases**. Each module can use its own database or you can group modules into a few databases.
This section will explain how to move Audit Logging, Setting Management and Permission Management module tables to a **second database** while the remaining modules continue to use the main ("Default") database.
@ -586,7 +173,7 @@ First step is to change the connection string section inside all the `appsetting
````json
"ConnectionStrings": {
"Default": "Server=localhost;Database=BookStore;Trusted_Connection=True"
"Default": "Server=(LocalDb)\MSSQLLocalDB;Database=BookStore;Trusted_Connection=True"
}
````
@ -594,128 +181,120 @@ Change it as shown below:
````json
"ConnectionStrings": {
"Default": "Server=localhost;Database=BookStore;Trusted_Connection=True",
"AbpPermissionManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True",
"AbpSettingManagement": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True",
"AbpAuditLogging": "Server=localhost;Database=BookStore_SecondDb;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=BookStore;Trusted_Connection=True",
"AbpPermissionManagement": "Server=(LocalDb)\\MSSQLLocalDB;Database=BookStore_SecondDb;Trusted_Connection=True",
"AbpSettingManagement": "Server=(LocalDb)\\MSSQLLocalDB;Database=BookStore_SecondDb;Trusted_Connection=True",
"AbpAuditLogging": "Server=(LocalDb)\MSSQLLocalDB;Database=BookStore_SecondDb;Trusted_Connection=True"
}
````
Added **three more connection strings** for the related module to target the `BookStore_SecondDb` database (they are all same). For example, `AbpPermissionManagement` is the connection string for the permission management module.
Added **three more connection strings** for the related module to target the `BookStore_SecondDb` database (they are all the same). For example, `AbpPermissionManagement` is the connection string name used by the permission management module.
The `AbpPermissionManagement` is a constant [defined](https://github.com/abpframework/abp/blob/97eaa6ff5a044f503465455c86332e5a277b077a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/AbpPermissionManagementDbProperties.cs#L11) by the permission management module. ABP Framework [connection string selection system](Connection-Strings.md) selects this connection string for the permission management module if you define. If you don't define, it fallbacks to the `Default` connection string.
### Create a Second Migration Project
### Create a Second DbContext
Defining the connection strings as explained above is enough **on runtime**. However, `BookStore_SecondDb` database doesn't exist yet. You need to create the database and the tables for the related modules.
Just like the main database, we want to use the EF Core Code First migration system to create and maintain the second database.
An easy way is to create a second project (`.csproj`) for the second migration `DbContext`.
So, create a new **class library project** in your solution named `Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb` (or name it better if you didn't like it).
The `.csproj` content should be something like that:
````xml
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Acme.BookStore.DbMigrationsForSecondDb</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Acme.BookStore.EntityFrameworkCore\Acme.BookStore.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0" />
</ItemGroup>
</Project>
````
You can just copy & modify the content of the original `.DbMigrations` project. This project references to the `.EntityFrameworkCore` project. **Only difference** is the `RootNamespace` value.
**Add a reference** to this project from the `.Web` project (otherwise, EF Core tooling doesn't allow to use the `Add-Migration` command).
### Create the Second DbMigrationDbContext
Create a new `DbContext` for the migrations and call the **extension methods** of the modules to configure the database tables for the related modules:
Just like the main database, we want to use the EF Core Code First migration system to create and maintain the second database. So, create a new `DbContext` class inside the `.EntityFrameworkCore` project:
````csharp
[ConnectionStringName("AbpPermissionManagement")]
public class BookStoreSecondMigrationsDbContext :
AbpDbContext<BookStoreSecondMigrationsDbContext>
using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
namespace BookStore.EntityFrameworkCore
{
public BookStoreSecondMigrationsDbContext(
DbContextOptions<BookStoreSecondMigrationsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
[ConnectionStringName("AbpPermissionManagement")]
public class BookStoreSecondDbContext :
AbpDbContext<BookStoreSecondDbContext>
{
base.OnModelCreating(builder);
public BookStoreSecondDbContext(
DbContextOptions<BookStoreSecondDbContext> options)
: base(options)
{
}
/* Include modules to your migration db context */
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureAuditLogging();
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureAuditLogging();
}
}
}
````
> `[ConnectionStringName(...)]` attribute is important here and tells to the ABP Framework which connection string should be used for this `DbContext`. We've used `AbpPermissionManagement`, but all are the same.
Create a **Design Time Db Factory** class, that is used by the EF Core tooling (by `Add-Migration` and `Update-Database` PCM commands for example):
We need to register this `BookStoreSecondDbContext` class to the dependency injection system. Open the `BookStoreEntityFrameworkCoreModule` class in the `BookStore.EntityFrameworkCore` project and add the following line into the `ConfigureServices` method:
````csharp
/* This class is needed for EF Core console commands
* (like Add-Migration and Update-Database commands) */
public class BookStoreSecondMigrationsDbContextFactory
: IDesignTimeDbContextFactory<BookStoreSecondMigrationsDbContext>
{
public BookStoreSecondMigrationsDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
context.Services.AddAbpDbContext<BookStoreSecondDbContext>();
````
var builder = new DbContextOptionsBuilder<BookStoreSecondMigrationsDbContext>()
.UseSqlServer(configuration.GetConnectionString("AbpPermissionManagement"));
We should also create a **Design Time Db Factory** class, that is used by the EF Core tooling (by `Add-Migration` and `Update-Database` PCM commands for example):
return new BookStoreSecondMigrationsDbContext(builder.Options);
}
````csharp
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
private static IConfigurationRoot BuildConfiguration()
namespace BookStore.EntityFrameworkCore
{
/* This class is needed for EF Core console commands
* (like Add-Migration and Update-Database commands) */
public class BookStoreSecondDbContextFactory
: IDesignTimeDbContextFactory<BookStoreSecondDbContext>
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false);
public BookStoreSecondDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var builder = new DbContextOptionsBuilder<BookStoreSecondDbContext>()
.UseSqlServer(configuration.GetConnectionString("AbpPermissionManagement"));
return new BookStoreSecondDbContext(builder.Options);
}
return builder.Build();
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../BookStore.DbMigrator/"))
.AddJsonFile("appsettings.json", optional: false);
return builder.Build();
}
}
}
````
This is similar to the class inside the `.EntityFrameworCore.DbMigrations` project, except this one uses the `AbpPermissionManagement` connection string.
Now, you can open the Package Manager Console, select the `.EntityFrameworkCore` project as the default project (make sure the `.Web` project is still the startup project) and run the following command:
Now, you can open the Package Manager Console, select the `.EntityFrameworkCore.DbMigrationsForSecondDb` project as the default project (make sure the `.Web` project is still the startup project) and run the `Add-Migration "Initial"` and `Update-Database` commands as shown below:
````bash
Add-Migration "Initial" -OutputDir "SecondDbMigrations" -Context BookStoreSecondDbContext
````
![pmc-add-migration-initial-update-database](images/pmc-add-migration-initial-update-database.png)
This will add a `SecondDbMigrations` folder in the `.EntityFrameworkCore` project and a migration class inside it. `OutputDir` and `Context` parameters are required since we currently have two `DbContext` class and two migrations folder in the same project.
Now, you should have a new database contains only the tables needed by the related modules:
You can now run the following command to create the database and the tables inside it:
![bookstore-second-database](images/bookstore-second-database.png)
````bash
Update-Database -Context BookStoreSecondDbContext
````
A new database, named `BookStore_SecondDb` should be created.
### Remove Modules from the Main Database
We've **created a second database** contains tables for the Audit Logging, Permission Management and Setting Management modules. So, we should **delete these tables from the main database**. It is pretty easy.
We've **created a second database** that contains tables for the Audit Logging, Permission Management and Setting Management modules. So, we should **delete these tables from the main database**. It is pretty easy.
First, remove the following lines from the `MigrationsDbContext` class (`BookStoreMigrationsDbContext` for this example):
First, remove the following lines from the `BookStoreDbContext` class:
````csharp
builder.ConfigurePermissionManagement();
@ -723,10 +302,10 @@ builder.ConfigureSettingManagement();
builder.ConfigureAuditLogging();
````
Open the Package Manager Console, select the `.EntityFrameworkCore.DbMigrations` as the Default project (make sure that the `.Web` project is still the startup project) and run the following command:
Open the Package Manager Console, select the `.EntityFrameworkCore` as the Default project (make sure that the `.Web` project is still the startup project) and run the following command:
````
Add-Migration "Removed_Audit_Setting_Permission_Modules"
Add-Migration "Removed_Audit_Setting_Permission_Modules" -Context BookStoreDbContext
````
This command will create a new migration class as shown below:
@ -764,122 +343,148 @@ Be careful in this step:
* If you have a **live system**, then you should care about the **data loss**. You need to move the table contents to the second database before deleting the tables.
* If you **haven't started** your project yet, you can consider to **remove all the migrations** and re-create the initial one to have a cleaner migration history.
Run the `Update-Database` command to delete the tables from your main database.
Run the following command to delete the tables from your main database:
````bash
Update-Database -Context BookStoreDbContext
````
Notice that you've also **deleted some initial seed data** (for example, permission grants for the admin role) if you haven't copied it to the new database. If you run the application, you may not login anymore. The solution is simple: **Re-run the `.DbMigrator` console application** in your solution, it will seed the new database.
### Automate the Second Database Schema Migration
`.DbMigrator` console application can run the database seed code across multiple databases, without any additional configuration. However, it can not run the EF Core Code First Migrations inside the second database migration project. Now, you will see how to configure the console migration application to handle both databases.
#### Implementing the IBookStoreDbSchemaMigrator
`.DbMigrator` console application can run the database seed code across multiple databases, without any additional configuration. However, it can not apply the EF Core Code First Migrations for the database of the `BookStoreSecondDbContext`. Now, you will see how to configure the console migration application to handle both databases.
`EntityFrameworkCoreBookStoreDbSchemaMigrator` class inside the `Acme.BookStore.EntityFrameworkCore.DbMigrations` project is responsible to migrate the database schema for the `BookStoreMigrationsDbContext`. It should be like that:
`EntityFrameworkCoreBookStoreDbSchemaMigrator` class inside the `Acme.BookStore.EntityFrameworkCore` project is responsible to migrate the database schema for the `BookStoreMigrationsDbContext`. It should be like that:
````csharp
[Dependency(ReplaceServices = true)]
public class EntityFrameworkCoreBookStoreDbSchemaMigrator
: IBookStoreDbSchemaMigrator, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using BookStore.Data;
using Volo.Abp.DependencyInjection;
public EntityFrameworkCoreBookStoreDbSchemaMigrator(
IServiceProvider serviceProvider)
namespace BookStore.EntityFrameworkCore
{
public class EntityFrameworkCoreBookStoreDbSchemaMigrator
: IBookStoreDbSchemaMigrator, ITransientDependency
{
_serviceProvider = serviceProvider;
}
private readonly IServiceProvider _serviceProvider;
public async Task MigrateAsync()
{
/* We are intentionally resolving the BookStoreMigrationsDbContext
* from IServiceProvider (instead of directly injecting it)
* to properly get the connection string of the current tenant in the
* current scope.
*/
await _serviceProvider
.GetRequiredService<BookStoreMigrationsDbContext>()
.Database
.MigrateAsync();
public EntityFrameworkCoreBookStoreDbSchemaMigrator(
IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task MigrateAsync()
{
/* We intentionally resolving the BookStoreDbContext
* from IServiceProvider (instead of directly injecting it)
* to properly get the connection string of the current tenant in the
* current scope.
*/
await _serviceProvider
.GetRequiredService<BookStoreDbContext>()
.Database
.MigrateAsync();
}
}
}
````
It implements the `IBookStoreDbSchemaMigrator` and **replaces existing services** (see the first line).
Add the following code inside the `MigrateAsync` method:
Remove the `[Dependency(ReplaceServices = true)]` line, because we will have two implementations of this interface and we want to use both. We don't want to replace one of them.
````csharp
await _serviceProvider
.GetRequiredService<BookStoreSecondDbContext>()
.Database
.MigrateAsync();
````
Create a copy of this class inside the new migration project (`Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb`), but use the `BookStoreSecondMigrationsDbContext`. Example implementation:
So, the `MigrateAsync` method should look like the following:
````csharp
public class EntityFrameworkCoreSecondBookStoreDbSchemaMigrator
: IBookStoreDbSchemaMigrator, ITransientDependency
public async Task MigrateAsync()
{
private readonly IServiceProvider _serviceProvider;
public EntityFrameworkCoreSecondBookStoreDbSchemaMigrator(
IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task MigrateAsync()
{
/* We are intentionally resolving the BookStoreSecondMigrationsDbContext
* from IServiceProvider (instead of directly injecting it)
* to properly get the connection string of the current tenant in the
* current scope.
*/
await _serviceProvider
.GetRequiredService<BookStoreSecondMigrationsDbContext>()
.Database
.MigrateAsync();
}
/* We intentionally resolving the BookStoreDbContext
* from IServiceProvider (instead of directly injecting it)
* to properly get the connection string of the current tenant in the
* current scope.
*/
await _serviceProvider
.GetRequiredService<BookStoreDbContext>()
.Database
.MigrateAsync();
await _serviceProvider
.GetRequiredService<BookStoreSecondDbContext>()
.Database
.MigrateAsync();
}
````
> Name of this class is important for [dependency injection](Dependency-Injection.md). It should end with `BookStoreDbSchemaMigrator` to be injectable by `IBookStoreDbSchemaMigrator` reference.
We, now, have two implementations of the `IBookStoreDbSchemaMigrator` interface, each one responsible to migrate the related database schema.
That's all. You can now run the `.DbMigrator` application to migrate & seed the databases. To test, you can delete both databases and run the `.DbMigrator` application again to see if it creates both of the databases.
#### Define a Module Class for the Second Migration Project
### Fixing the Tests
It is time to define the [module](Module-Development-Basics.md) class for this second migrations (`Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb`) project:
Creating a new DbContext will break the integration tests. It is easy to fix. Open the `BookStoreEntityFrameworkCoreTestModule` class in the `BookStore.EntityFrameworkCore.Tests` project, find the `CreateDatabaseAndGetConnection` method. It should be like that:
````csharp
[DependsOn(
typeof(BookStoreEntityFrameworkCoreModule)
)]
public class BookStoreEntityFrameworkCoreSecondDbMigrationsModule : AbpModule
private static SqliteConnection CreateDatabaseAndGetConnection()
{
public override void ConfigureServices(ServiceConfigurationContext context)
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var options = new DbContextOptionsBuilder<BookStoreDbContext>()
.UseSqlite(connection)
.Options;
using (var context = new BookStoreDbContext(options))
{
context.Services.AddAbpDbContext<BookStoreSecondMigrationsDbContext>();
context.GetService<IRelationalDatabaseCreator>().CreateTables();
}
return connection;
}
````
Now, reference `Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb` project from the `Acme.BookStore.DbMigrator` project and `typeof(BookStoreEntityFrameworkCoreSecondDbMigrationsModule)` to the dependency list of the `BookStoreDbMigratorModule`. `BookStoreDbMigratorModule` class should be something like that:
Change it as the following:
````csharp
[DependsOn(
typeof(AbpAutofacModule),
typeof(BookStoreEntityFrameworkCoreDbMigrationsModule),
typeof(BookStoreEntityFrameworkCoreSecondDbMigrationsModule), // ADDED THIS!
typeof(BookStoreApplicationContractsModule)
)]
public class BookStoreDbMigratorModule : AbpModule
private static SqliteConnection CreateDatabaseAndGetConnection()
{
...
}
````
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
We had a reference to the `Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb` project from the `Acme.BookStore.Web` project, but hadn't added module dependency since we hadn't created it before. But, now we have it and we need to add `typeof(BookStoreEntityFrameworkCoreSecondDbMigrationsModule)` to the dependency list of the `BookStoreWebModule` class.
var options = new DbContextOptionsBuilder<BookStoreDbContext>()
.UseSqlite(connection)
.Options;
#### Run the Database Migrator!
using (var context = new BookStoreDbContext(options))
{
context.GetService<IRelationalDatabaseCreator>().CreateTables();
}
You can run the `.DbMigrator` application to migrate & seed the databases. To test, you can delete both databases and run the `.DbMigrator` application again to see if it creates both of the databases.
// Add the following code --------------
var optionsForSecondDb = new DbContextOptionsBuilder<BookStoreSecondDbContext>()
.UseSqlite(connection)
.Options;
using (var context = new BookStoreSecondDbContext(optionsForSecondDb))
{
context.GetService<IRelationalDatabaseCreator>().CreateTables();
}
//--------------------------------------
return connection;
}
````
Integration tests now will work. I've used the same database in the tests to keep it simple.
## Separating Host & Tenant Database Schemas
@ -887,7 +492,7 @@ In a multi-tenant solution, you may want to separate your database schemas, so h
Some pre-built ABP modules are related only with the host side, like the [Tenant Management](Modules/Tenant-Management.md) module. So, in the tenant `DbContext` class you don't call `modelBuilder.ConfigureTenantManagement()` and that's all.
However, some modules, like the [Identity](Modules/Identity.md) module, is both used in host and tenant sides. It stores tenant users in the tenant database and host users in the host database. However, it stores some entities, like `IdentityClaimType`, only in the host side. In this case, you don't want to add these tables in the tenant database, even if they are not used and will always be empty.
Some modules, like the [Identity](Modules/Identity.md) module, is both used in host and tenant sides. It stores tenant users in the tenant database and host users in the host database. However, it stores some entities, like `IdentityClaimType`, only in the host side. In this case, you don't want to add these tables in the tenant database, even if they are not used and will always be empty for tenants.
ABP provides a simple way to set the multi-tenancy side for a `DbContext`, so the modules can check it and decide to map tables to the database, or not.
@ -899,6 +504,7 @@ public class MyTenantDbContext : AbpDbContext<MyTenantDbContext>
modelBuilder.SetMultiTenancySide(MultiTenancySides.Tenant);
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureIdentity();
modelBuilder.ConfigureFeatureManagement();
modelBuilder.ConfigureAuditLogging();
@ -948,4 +554,4 @@ This document explains how to split your databases and manage your database migr
## Source Code
You can find the source code of the example project referenced by this document [here](https://github.com/abpframework/abp-samples/tree/master/EfCoreMigrationDemo). However, you need to read and understand this document in order to understand the example project's source code.
You can find the source code of the example project referenced by this document [here](https://github.com/abpframework/abp-samples/tree/master/EfCoreMigrationDemo). You can also find the changes explained in this document as a [single commit](https://github.com/abpframework/abp-samples/pull/95/commits/c2ffd76175e0a6fdfcf6477bbaea23dc2793fedd).

6
docs/en/Entity-Framework-Core-MySQL.md

@ -15,7 +15,7 @@ Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFra
Find `UseSqlServer()` calls in your solution. Check the following files:
* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySQL()`.
* *YourProjectName*MigrationsDbContextFactory.cs inside the `.EntityFrameworkCore.DbMigrations` project. Replace `UseSqlServer()` with `UseMySql()`. Then add a new parameter (`ServerVersion`) to `UseMySql()` method. Example: `.UseMySql(configuration.GetConnectionString("Default"), ServerVersion.FromString("8.0.21-mysql"))`. See [this issue](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1233) for more information about `ServerVersion`)
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySql()`. Then add a new parameter (`ServerVersion`) to `UseMySql()` method. Example: `.UseMySql(configuration.GetConnectionString("Default"), ServerVersion.FromString("8.0.21-mysql"))`. See [this issue](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1233) for more information about `ServerVersion`)
> Depending on your solution structure, you may find more code files need to be changed.
@ -29,8 +29,8 @@ You typically will change the `appsettings.json` inside the `.DbMigrator` and `.
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core Migrations depend on the selected DBMS provider. So, changing the DBMS provider will cause the migration fails.
* Delete the Migrations folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the Migrations folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will create a database migration with all database objects (tables) configured.

14
docs/en/Entity-Framework-Core-Oracle-Devart.md

@ -19,20 +19,20 @@ Also replace `using Volo.Abp.EntityFrameworkCore.SqlServer;` with `using Volo.Ab
Find `UseSqlServer()` calls in your solution, replace with `UseOracle()`. Check the following files:
* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project.
* *YourProjectName*MigrationsDbContextFactory.cs inside the `.EntityFrameworkCore.DbMigrations` project.
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project.
In the `CreateDbContext()` method of the *YourProjectName*MigrationsDbContextFactory.cs, replace the following code block
In the `CreateDbContext()` method of the *YourProjectName*DbContextFactory.cs, replace the following code block
```csharp
var builder = new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>()
var builder = new DbContextOptionsBuilder<YourProjectNameDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
```
with this one
```csharp
var builder = (DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>)
new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>().UseOracle
var builder = (DbContextOptionsBuilder<YourProjectNameDbContext>)
new DbContextOptionsBuilder<YourProjectNameDbContext>().UseOracle
(
configuration.GetConnectionString("Default")
);
@ -51,8 +51,8 @@ You typically will change the `appsettings.json` inside the `.DbMigrator` and `.
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) by default.
EF Core Migrations depend on the selected DBMS provider. Changing the DBMS provider, may not work with the existing migrations.
* Delete the `Migrations` folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console window (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the `Migrations` folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console window (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will scaffold a new migration for Oracle.

12
docs/en/Entity-Framework-Core-Oracle-Official.md

@ -17,19 +17,19 @@ Also replace `using Volo.Abp.EntityFrameworkCore.SqlServer;` with `using Volo.Ab
Find `UseSqlServer()` calls in your solution, replace with `UseOracle()`. Check the following files:
* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project.
* *YourProjectName*MigrationsDbContextFactory.cs inside the `.EntityFrameworkCore.DbMigrations` project.
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project.
In the `CreateDbContext()` method of the *YourProjectName*MigrationsDbContextFactory.cs, replace the following code block
In the `CreateDbContext()` method of the *YourProjectName*DbContextFactory.cs, replace the following code block
```csharp
var builder = new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>()
var builder = new DbContextOptionsBuilder<YourProjectNameDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
```
with this one (just changes `UseSqlServer(...)` to `UseOracle(...)`)
```csharp
var builder = new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>()
var builder = new DbContextOptionsBuilder<YourProjectNameDbContext>()
.UseOracle(configuration.GetConnectionString("Default"));
```
@ -46,8 +46,8 @@ You typically will change the `appsettings.json` inside the `.DbMigrator` and `.
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) by default.
EF Core Migrations depend on the selected DBMS provider. Changing the DBMS provider, may not work with the existing migrations.
* Delete the `Migrations` folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console window (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the `Migrations` folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console window (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will scaffold a new migration for Oracle.

26
docs/en/Entity-Framework-Core-Other-DBMS.md

@ -62,20 +62,18 @@ MySQL connection strings are different than SQL Server connection strings. So, c
You typically will change the `appsettings.json` inside the `.DbMigrator` and `.Web` projects, but it depends on your solution structure.
## Change the Migrations DbContext
## DBMS restrictions
MySQL DBMS has some slight differences than the SQL Server. Some module database mapping configuration (especially the field lengths) causes problems with MySQL. For example, some of the the [IdentityServer module](Modules/IdentityServer.md) tables has such problems and it provides an option to configure the fields based on your DBMS.
The startup template contains a *YourProjectName*MigrationsDbContext which is responsible to maintain and migrate the database schema. This DbContext basically calls extension methods of the depended modules to configure their database tables.
Open the *YourProjectName*MigrationsDbContext and change the `builder.ConfigureIdentityServer();` line as shown below:
The module may provide some built-in solutions. You can configure it via `ModelBuilder`. eg: `Identity Server` module.
````csharp
```csharp
builder.ConfigureIdentityServer(options =>
{
options.DatabaseProvider = EfCoreDatabaseProvider.MySql;
});
````
```
Then `ConfigureIdentityServer()` method will set the field lengths to not exceed the MySQL limits. Refer to related module documentation if you have any problem while creating or executing the database migrations.
@ -83,8 +81,8 @@ Then `ConfigureIdentityServer()` method will set the field lengths to not exceed
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core Migrations depend on the selected DBMS provider. So, changing the DBMS provider will cause the migration fails.
* Delete the Migrations folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the Migrations folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will create a database migration with all database objects (tables) configured.
@ -94,16 +92,4 @@ Run the `.DbMigrator` project to create the database and seed the initial data.
It is ready. Just run the application and enjoy coding.
## DBMS restrictions
Different DBMS may have some restrictions, such as the maximum length of field names, index length, etc.
The module may provide some built-in solutions. You can configure it via `ModelBuilder`. eg: `Identity Server` module.
```csharp
builder.ConfigureIdentityServer(options =>
{
options.DatabaseProvider = EfCoreDatabaseProvider.MySql;
});
```
Related discussions: https://github.com/abpframework/abp/issues/1920

6
docs/en/Entity-Framework-Core-PostgreSQL.md

@ -15,7 +15,7 @@ Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFra
Find `UseSqlServer()` call in *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project and replace with `UseNpgsql()`.
Find `UseSqlServer()` call in *YourProjectName*MigrationsDbContextFactory.cs inside the `.EntityFrameworkCore.DbMigrations` project and replace with `UseNpgsql()`.
Find `UseSqlServer()` call in *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project and replace with `UseNpgsql()`.
> Depending on your solution structure, you may find more `UseSqlServer()` calls that needs to be changed.
@ -29,8 +29,8 @@ You typically will change the `appsettings.json` inside the `.DbMigrator` and `.
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core Migrations depend on the selected DBMS provider. So, changing the DBMS provider will cause the migration fails.
* Delete the Migrations folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the Migrations folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will create a database migration with all database objects (tables) configured.

6
docs/en/Entity-Framework-Core-SQLite.md

@ -15,7 +15,7 @@ Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFra
Find `UseSqlServer()` calls in your solution, replace with `UseSqlite()`. Check the following files:
* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project.
* *YourProjectName*MigrationsDbContextFactory.cs inside the `.EntityFrameworkCore.DbMigrations` project.
* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project.
> Depending on your solution structure, you may find more code files need to be changed.
@ -39,8 +39,8 @@ You typically will change the `appsettings.json` inside the `.DbMigrator` and `.
The startup template uses [Entity Framework Core's Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). EF Core Migrations depend on the selected DBMS provider. So, changing the DBMS provider will cause the migration fails.
* Delete the Migrations folder under the `.EntityFrameworkCore.DbMigrations` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore.DbMigrations` project as the default project in the Package Manager Console).
* Delete the Migrations folder under the `.EntityFrameworkCore` project and re-build the solution.
* Run `Add-Migration "Initial"` on the Package Manager Console (select the `.DbMigrator` (or `.Web`) project as the startup project in the Solution Explorer and select the `.EntityFrameworkCore` project as the default project in the Package Manager Console).
This will create a database migration with all database objects (tables) configured.

2
docs/en/Global-Features.md

@ -8,8 +8,6 @@ Global Features system is especially useful if you want to develop a reusable ap
## Installation
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
### Using the ABP CLI
Open a command line window in the folder of the project (.csproj file) and type the following command:
```bash

48
docs/en/Local-Event-Bus.md

@ -158,7 +158,53 @@ If you perform **database operations** and use the [repositories](Repositories.m
> The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options.
## Transaction & Exception Behavior
## Exception Handling
ABP provides exception handling and retries when an exception occurs.
Enable exception handling:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy();
});
}
```
When an exception occurs, it will retry every three seconds up to the maximum number of retries(default is 3) and throw the original exception, you can change the number of retries and the retry interval:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### Error Handle Selector
By default all event types will be exception handling, you can use `ErrorHandleSelector` of `AbpEventBusOptions` to change it:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` actually a list of type predicate. You can write a lambda expression to define your filter.
### Customize Exception Handling
ABP defines the `IEventErrorHandler` interface and implemented by `LocalEventErrorHandler`, you can replace it via [dependency injection](Dependency-Injection.md)
### Transaction & Exception Behavior
When an event published, subscribed event handlers are immediately executed. So;

8
docs/en/Modules/Docs.md

@ -38,7 +38,7 @@ Note that this document covers `Entity Framework Core` provider but you can also
### 2- Running The Empty Application
After you download the project, extract the ZIP file and open `Acme.MyProject.sln`. You will see that the solution consists of `Application`, `Application.Contracts`, `DbMigrator`, `Domain`, `Domain.Shared`, `EntityFrameworkCore`, `EntityFrameworkCore.DbMigations`, `HttpApi`, `HttpApi.Client` and `Web` projects. Right click on `Acme.MyProject.Web` project and **Set as StartUp Project**.
After you download the project, extract the ZIP file and open `Acme.MyProject.sln`. You will see that the solution consists of `Application`, `Application.Contracts`, `DbMigrator`, `Domain`, `Domain.Shared`, `EntityFrameworkCore`, `HttpApi`, `HttpApi.Client` and `Web` projects. Right click on `Acme.MyProject.Web` project and **Set as StartUp Project**.
![Create a new project](../images/docs-module_solution-explorer.png)
@ -237,15 +237,15 @@ If you choose Entity Framework as your database provider, you need to configure
}
```
* Open `Package Manager Console` in `Visual Studio` and choose `Acme.MyProject.EntityFrameworkCore.DbMigrations` as default project. Then write the below command to add the migration for Docs Module.
* Open `Package Manager Console` in `Visual Studio` and choose `Acme.MyProject.EntityFrameworkCore` as default project. Then write the below command to add the migration for Docs Module.
```csharp
add-migration Added_Docs_Module
```
When the command successfully executes , you will see a new migration file named as `20181221111621_Added_Docs_Module` in the folder `Acme.MyProject.EntityFrameworkCore.DbMigrations\Migrations`.
When the command successfully executes , you will see a new migration file named as `20181221111621_Added_Docs_Module` in the folder `Acme.MyProject.EntityFrameworkCore\Migrations`.
Now, update the database for Docs module database changes. To do this run the below code on `Package Manager Console` in `Visual Studio`. Be sure `Acme.MyProject.EntityFrameworkCore.DbMigrations` is still default project.
Now, update the database for Docs module database changes. To do this run the below code on `Package Manager Console` in `Visual Studio`. Be sure `Acme.MyProject.EntityFrameworkCore` is still default project.
```csharp
update-database

4
docs/en/Repositories.md

@ -222,8 +222,8 @@ public class PersonRepository : EfCoreRepository<MyDbContext, Person, Guid>, IPe
public async Task<Person> FindByNameAsync(string name)
{
var dbSet = await GetDbSetAsync();
return await dbSet.Set<Person>()
var dbContext = await GetDbContextAsync();
return await dbContext.Set<Person>()
.Where(p => p.Name == name)
.FirstOrDefaultAsync();
}

14
docs/en/Road-Map.md

@ -4,24 +4,14 @@ This document provides a road map, release schedule and planned features for the
## Next Versions
### v4.4
This version will focus on **documentation** and **improvements** of current features. In addition, the following features are planned:
* Revisit the microservice demo solution ([#8385](https://github.com/abpframework/abp/issues/8385))
* A new UI Theme alternative to the Basic Theme ([#6132](https://github.com/abpframework/abp/issues/6132))
* Improvements and new features to the [CMS Kit](Modules/Cms-Kit.md) module ([#8380](https://github.com/abpframework/abp/issues/8380) [#8381](https://github.com/abpframework/abp/issues/8381))
* Razor engine support for text templating ([#8373](https://github.com/abpframework/abp/issues/8373))
**Planned release date**: End of Quarter 2, 2021. See the [4.4 milestone](https://github.com/abpframework/abp/milestone/52) to track the progress.
### v5.0
We planned to focus on the ABP Framework v5.0 after the 4.4 release. This version will focus on the following works:
This version will focus on the following works:
* Upgrading to .NET 6.0 ([#9004](https://github.com/abpframework/abp/issues/9004))
* Upgrading to Bootstrap 5.x ([#8922](https://github.com/abpframework/abp/issues/8922))
* Alternative to IdentityServer4 ([#7221](https://github.com/abpframework/abp/issues/7221))
* Revisit the microservice demo solution ([#8385](https://github.com/abpframework/abp/issues/8385))
* Dapr integration ([#2183](https://github.com/abpframework/abp/issues/2183))
* Publishing distributed events as transactional ([#6126](https://github.com/abpframework/abp/issues/6126))
* Resource based authorization system ([#236](https://github.com/abpframework/abp/issues/236))

18
docs/en/Startup-Templates/Application.md

@ -128,20 +128,6 @@ This is the integration project for the EF Core. It defines the `DbContext` and
> This project is available only if you are using EF Core as the database provider. If you select another database provider, its name will be different.
#### .EntityFrameworkCore.DbMigrations Project
Contains EF Core database migrations for the solution. It has a separated `DbContext` to dedicated to manage migrations.
ABP is a modular framework and with an ideal design, each module has its own `DbContext` class. This is where the migration `DbContext` comes into play and unifies all `DbContext` configurations into a single model to maintain a single database schema. For more advanced scenarios, you can have multiple databases (each contains a single or a few module tables) and multiple migration `DbContext`s (each maintains a different database schema).
Notice that the migration `DbContext` is only used for database migrations and *not used on runtime*.
* Depends on the `.EntityFrameworkCore` project since it re-uses the configuration defined for the `DbContext` of the application.
> This project is available only if you are using EF Core as the database provider.
>
> See the [Entity Framework Core Migrations Guide](../Entity-Framework-Core-Migrations.md) to understand this project in details.
#### .DbMigrator Project
This is a console application which simplifies to execute database migrations on development and production environments. When you run this application, it;
@ -156,7 +142,7 @@ Especially, seeding initial data is important at this point. ABP has a modular d
While creating database & applying migrations seems only necessary for relational databases, this projects comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds initial data which is necessary for the application.
* Depends on the `.EntityFrameworkCore.DbMigrations` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.Application.Contracts` project to be able to access permission definitions, because initial data seeder grants all permissions for the admin role by default.
#### .HttpApi Project
@ -187,7 +173,7 @@ This project contains the main `appsettings.json` file that contains the connect
* Depends on the `.HttpApi` since UI layer needs to use APIs and application service interfaces of the solution.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore.DbMigrations` projects.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects.
>
> These references are actually not needed while coding your UI layer, because UI layer normally doesn't depend on the EF Core or the Application layer's implementation. This startup templates are ready for the tiered deployment, where API layer is hosted in a separate server than the UI layer.
>

28
docs/en/Tutorials/Part-1.md

@ -142,28 +142,36 @@ public class BookStoreMongoDbContext : AbpMongoDbContext
### Map the Book Entity to a Database Table
Open `BookStoreDbContextModelCreatingExtensions.cs` file in the `Acme.BookStore.EntityFrameworkCore` project and add the mapping code for the `Book` entity. The final class should be the following:
Locate to `OnModelCreating` method in the `BookStoreDbContext` class and add the mapping code for the `Book` entity:
````csharp
using Acme.BookStore.Books;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
...
namespace Acme.BookStore.EntityFrameworkCore
{
public static class BookStoreDbContextModelCreatingExtensions
public class BookStoreDbContext :
AbpDbContext<BookStoreDbContext>,
IIdentityDbContext,
ITenantManagementDbContext
{
public static void ConfigureBookStore(this ModelBuilder builder)
...
protected override void OnModelCreating(ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
base.OnModelCreating(builder);
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
...
/* Configure your own tables/entities inside here */
builder.Entity<Book>(b =>
{
b.ToTable(BookStoreConsts.DbTablePrefix + "Books",
BookStoreConsts.DbSchema);
BookStoreConsts.DbSchema);
b.ConfigureByConvention(); //auto configure for the base class props
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});
@ -179,7 +187,7 @@ namespace Acme.BookStore.EntityFrameworkCore
The startup solution is configured to use [Entity Framework Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). Since we've changed the database mapping configuration, we should create a new migration and apply changes to the database.
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore.DbMigrations` project and type the following command:
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore` project and type the following command:
```bash
dotnet ef migrations add Created_Book_Entity
@ -189,7 +197,7 @@ This will add a new migration class to the project:
![bookstore-efcore-migration](./images/bookstore-efcore-migration.png)
> If you are using Visual Studio, you may want to use `Add-Migration Created_Book_Entity -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC.
> If you are using Visual Studio, you may want to use `Add-Migration Created_Book_Entity -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore` is the *Default Project* in PMC.
{{end}}

6
docs/en/Tutorials/Part-10.md

@ -70,7 +70,7 @@ We prefer to **delete the database** {{if DB=="EF"}}(you can run the `Drop-Datab
### Update the EF Core Mapping
Open the `BookStoreDbContextModelCreatingExtensions` class under the `EntityFrameworkCore` folder of the `Acme.BookStore.EntityFrameworkCore` project and change the `builder.Entity<Book>` part as shown below:
Locate to `OnModelCreating` method in the `BookStoreDbContext` class that under the `EntityFrameworkCore` folder of the `Acme.BookStore.EntityFrameworkCore` project and change the `builder.Entity<Book>` part as shown below:
````csharp
builder.Entity<Book>(b =>
@ -88,7 +88,7 @@ builder.Entity<Book>(b =>
The startup solution is configured to use [Entity Framework Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). Since we've changed the database mapping configuration, we should create a new migration and apply changes to the database.
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore.DbMigrations` project and type the following command:
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore` project and type the following command:
````bash
dotnet ef migrations add Added_AuthorId_To_Book
@ -121,7 +121,7 @@ migrationBuilder.AddForeignKey(
* Creates an index on the `AuthorId` field.
* Declares the foreign key to the `AppAuthors` table.
> If you are using Visual Studio, you may want to use `Add-Migration Added_AuthorId_To_Book -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC.
> If you are using Visual Studio, you may want to use `Add-Migration Added_AuthorId_To_Book -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore` is the *Default Project* in PMC.
{{end}}

4
docs/en/Tutorials/Part-4.md

@ -52,7 +52,7 @@ This part covers the **server side** tests. There are several test projects in t
Each project is used to test the related project. Test projects use the following libraries for testing:
* [Xunit](https://xunit.github.io/) as the main test framework.
* [Xunit](https://github.com/xunit/xunit) as the main test framework.
* [Shoudly](https://github.com/shouldly/shouldly) as the assertion library.
* [NSubstitute](http://nsubstitute.github.io/) as the mocking library.
@ -249,4 +249,4 @@ Congratulations, the **green icons** indicates that the tests have been successf
## The Next Part
See the [next part](Part-5.md) of this tutorial.
See the [next part](Part-5.md) of this tutorial.

6
docs/en/Tutorials/Part-7.md

@ -48,7 +48,7 @@ Open the `BookStoreDbContext` in the `Acme.BookStore.EntityFrameworkCore` projec
public DbSet<Author> Authors { get; set; }
````
Then open the `BookStoreDbContextModelCreatingExtensions` class in the same project and add the following lines to the end of the `ConfigureBookStore` method:
Then locate to the `OnModelCreating` method in `BookStoreDbContext` class in the same project and add the following lines to the end of the method:
````csharp
builder.Entity<Author>(b =>
@ -72,7 +72,7 @@ This is just like done for the `Book` entity before, so no need to explain again
The startup solution is configured to use [Entity Framework Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). Since we've changed the database mapping configuration, we should create a new migration and apply changes to the database.
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore.DbMigrations` project and type the following command:
Open a command-line terminal in the directory of the `Acme.BookStore.EntityFrameworkCore` project and type the following command:
````bash
dotnet ef migrations add Added_Authors
@ -88,7 +88,7 @@ You can apply changes to the database using the following command, in the same c
dotnet ef database update
````
> If you are using Visual Studio, you may want to use `Add-Migration Added_Authors -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC.
> If you are using Visual Studio, you may want to use `Add-Migration Added_Authors -c BookStoreMigrationsDbContext` and `Update-Database -c BookStoreMigrationsDbContext` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} is the startup project and `Acme.BookStore.EntityFrameworkCore` is the *Default Project* in PMC.
{{else if DB=="Mongo"}}

16
docs/en/Tutorials/Todo/Index.md

@ -151,13 +151,19 @@ Open the `TodoAppDbContext` class in the `EntityFrameworkCore` folder of the *To
public DbSet<TodoItem> TodoItems { get; set; }
````
Then open the `TodoAppDbContextModelCreatingExtensions` class in the same folder and add a mapping configuration for the `TodoItem` class as shown below:
Then locate to `OnModelCreating` method in the `TodoAppDbContext` class and add the mapping code for the `TodoItem ` entity:
````csharp
public static void ConfigureTodoApp(this ModelBuilder builder)
protected override void OnModelCreating(ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
base.OnModelCreating(builder);
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
...
/* Configure your own tables/entities inside here */
builder.Entity<TodoItem>(b =>
{
b.ToTable("TodoItems");
@ -171,7 +177,7 @@ We've mapped `TodoItem` entity to a `TodoItems` table in the database.
The startup solution is configured to use Entity Framework Core [Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations). Since we've changed the database mapping configuration, we should create a new migration and apply changes to the database.
Open a command-line terminal in the directory of the *TodoApp.EntityFrameworkCore.DbMigrations* project and type the following command:
Open a command-line terminal in the directory of the *TodoApp.EntityFrameworkCore* project and type the following command:
````bash
dotnet ef migrations add Added_TodoItem
@ -187,7 +193,7 @@ You can apply changes to the database using the following command, in the same c
dotnet ef database update
````
> If you are using Visual Studio, you may want to use `Add-Migration Added_TodoItem` and `Update-Database` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} is the startup project and `TodoApp.EntityFrameworkCore.DbMigrations` is the *Default Project* in PMC.
> If you are using Visual Studio, you may want to use `Add-Migration Added_TodoItem` and `Update-Database` commands in the *Package Manager Console (PMC)*. In this case, ensure that {{if UI=="MVC"}}`TodoApp.Web`{{else if UI=="BlazorServer"}}`TodoApp.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`TodoApp.HttpApi.Host`{{end}} is the startup project and `TodoApp.EntityFrameworkCore` is the *Default Project* in PMC.
{{else if DB=="Mongo"}}

BIN
docs/en/Tutorials/Todo/todo-efcore-migration.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
docs/en/Tutorials/images/bookstore-efcore-migration-authors.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
docs/en/Tutorials/images/bookstore-efcore-migration.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

2
docs/en/UI/AspNetCore/Theming.md

@ -36,7 +36,7 @@ All the themes must depend on the [@abp/aspnetcore.mvc.ui.theme.shared](https://
* [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library.
* [SweetAlert](https://sweetalert.js.org/) to show fancy alert message and confirmation dialogs.
* [Toastr](https://github.com/CodeSeven/toastr) to show toast notifications.
* [Lodesh](https://lodash.com/) as a utility library.
* [Lodash](https://lodash.com/) as a utility library.
* [Luxon](https://moment.github.io/luxon/) for date/time operations.
* [JQuery Form](https://github.com/jquery-form/form) for AJAX forms.
* [bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker) to show date pickers.

2
docs/en/Upgrading.md

@ -22,7 +22,7 @@ Run this command in the terminal while you are in the root folder of your soluti
When you upgrade to a new version, it is good to check if there is a database schema change and upgrade your database schema if your database provider is **Entity Framework Core**;
* Use `Add-Migration "Upgraded_To_Abp_4_1"` or a similar command in the Package Manager Console (PMC) to create a new migration (Set the `EntityFrameworkCore.DbMigrations` as the Default project in the PMC and `.DbMigrator` as the Startup Project in the Solution Explorer, in the Visual Studio).
* Use `Add-Migration "Upgraded_To_Abp_4_1"` or a similar command in the Package Manager Console (PMC) to create a new migration (Set the `EntityFrameworkCore` as the Default project in the PMC and `.DbMigrator` as the Startup Project in the Solution Explorer, in the Visual Studio).
* Run the `.DbMigrator` application to upgrade the database and seed the initial data.
If `Add-Migration` generates an empty migration, you can use `Remove-Migration` to delete it before executing the `.DbMigrator`.

139
docs/en/docs-nav.json

@ -102,11 +102,7 @@
"path": "CLI.md",
"items": [
{
"text": "Build Command",
"path": "CLI-BuildCommand.md"
},
{
"text": "Create Solution Sample Commands",
"text": "Examples for the new command",
"path": "CLI-New-Command-Samples.md"
}
]
@ -418,26 +414,13 @@
"text": "Plug-In Modules",
"path": "PlugIn-Modules.md"
},
{
"text": "Customizing/Extending Modules",
"path": "Customizing-Application-Modules-Guide.md"
},
{
"text": "Customizing/Extending Entities",
"path": "Customizing-Application-Modules-Extending-Entities.md"
},
{
"text": "Customizing/Overriding Services",
"path": "Customizing-Application-Modules-Overriding-Services.md"
},
{
"text": "Module Entity Extensions",
"path": "Module-Entity-Extensions.md"
},
{
"text": "Best Practices",
"path": "Best-Practices/Index.md",
"items": [
{
"text": "Overall",
"path": "Best-Practices/Index.md"
},
{
"text": "Module Architecture",
"path": "Best-Practices/Module-Architecture.md"
@ -486,6 +469,28 @@
]
}
]
},
{
"text": "Customizing/Extending Modules",
"path": "Customizing-Application-Modules-Guide.md",
"items": [
{
"text": "Overall",
"path": "Customizing-Application-Modules-Guide.md"
},
{
"text": "Module Entity Extension System",
"path": "Module-Entity-Extensions.md"
},
{
"text": "Customizing/Extending Entities",
"path": "Customizing-Application-Modules-Extending-Entities.md"
},
{
"text": "Customizing/Overriding Services",
"path": "Customizing-Application-Modules-Overriding-Services.md"
}
]
}
]
},
@ -503,10 +508,6 @@
"text": "Entities & Aggregate Roots",
"path": "Entities.md"
},
{
"text": "Multi Lingual Entities",
"path": "Multi-Lingual-Entities.md"
},
{
"text": "Value Objects",
"path": "Value-Objects.md"
@ -733,19 +734,24 @@
},
{
"text": "Customize/Extend the UI",
"path": "UI/AspNetCore/Customization-User-Interface.md"
},
{
"text": "Entity Action Extensions",
"path": "UI/AspNetCore/Entity-Action-Extensions.md"
},
{
"text": "Data Table Column Extensions",
"path": "UI/AspNetCore/Data-Table-Column-Extensions.md"
},
{
"text": "Page Toolbar Extensions",
"path": "UI/AspNetCore/Page-Toolbar-Extensions.md"
"items": [
{
"text": "Overall",
"path": "UI/AspNetCore/Customization-User-Interface.md"
},
{
"text": "Entity Action Extensions",
"path": "UI/AspNetCore/Entity-Action-Extensions.md"
},
{
"text": "Data Table Column Extensions",
"path": "UI/AspNetCore/Data-Table-Column-Extensions.md"
},
{
"text": "Page Toolbar Extensions",
"path": "UI/AspNetCore/Page-Toolbar-Extensions.md"
}
]
}
]
},
@ -1122,11 +1128,11 @@
"path": "Entity-Framework-Core-Oracle.md",
"items": [
{
"text": "Oracle",
"text": "Oracle (Official)",
"path": "Entity-Framework-Core-Oracle-Official.md"
},
{
"text": "Oracle Devart",
"text": "Oracle (Devart)",
"path": "Entity-Framework-Core-Oracle-Devart.md"
}
]
@ -1257,56 +1263,7 @@
},
{
"text": "Migration Guides",
"path": "Migration-Guides/Index.md",
"items": [
{
"text": "MVC / Razor Pages",
"items": [
{
"text": "3.3 to 4.0",
"path": "Migration-Guides/Abp-4_0-MVC-Razor-Pages.md"
}
]
},
{
"text": "Blazor",
"items": [
{
"text": "3.2 to 3.3",
"path": "Migration-Guides/BlazorUI-3_3.md"
},
{
"text": "3.3 to 4.0",
"path": "Migration-Guides/Abp-4_0-Blazor.md"
}
]
},
{
"text": "Angular",
"items": [
{
"text": "3.3 to 4.0",
"path": "Migration-Guides/Abp-4_0-Angular.md"
}
]
},
{
"text": "3.3 to 4.0",
"path": "Migration-Guides/Abp-4_0.md"
},
{
"text": "4.2",
"path": "Migration-Guides/Abp-4_2.md"
},
{
"text": "4.x to 4.3",
"path": "Migration-Guides/Abp-4_3.md"
},
{
"text": "Upgrading the Startup Template",
"path": "Migration-Guides/Upgrading-Startup-Template.md"
}
]
"path": "Migration-Guides/Index.md"
}
]
},

BIN
docs/en/images/bookstore-visual-studio-solution-v3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/images/docs-module_solution-explorer.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

466
docs/pt-BR/MongoDB.md

@ -0,0 +1,466 @@
# Integração do MongoDB
Este documento explica como integrar e configurar o MongoDB como um provedor de banco de dados para aplicações baseadas no ABP.
## Instalação
`Volo.Abp.MongoDB` é o pacote nuget principal para a integração do MongoDB. Instale-o em seu projeto (para uma aplicação em camadas, será sua camada de dados ou infraestrutura):
```
Install-Package Volo.Abp.MongoDB
```
Então adicione a dependência de módulo `AbpMongoDbModule` para o seu [module](Module-Development-Basics.md):
```c#
using Volo.Abp.MongoDB;
using Volo.Abp.Modularity;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpMongoDbModule))]
public class MyModule : AbpModule
{
// ...
}
}
```
## Criando um Mongo Db Context
ABP apresenta o conceito **Mongo Db Context** (que é semelhante ao Entity Framework Core DbContext) para tornar mais fácil usar coleções e configurá-las. Um exemplo é mostrado abaixo:
```c#
public class MyDbContext : AbpMongoDbContext
{
public IMongoCollection<Question> Questions => Collection<Question>();
public IMongoCollection<Category> Categories => Collection<Category>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
// Personalize a configuração para as suas collections.
}
}
```
* É derivado da classe `AbpMongoDbContext`.
* Adiciona uma propriedade pública `IMongoCollection<TEntity>` para cada mongo collection. Por padrão ABP usa essas propriedades para criar repositórios padrão.
* Substituir o método `CreateModel` permite definir a configuração da collection.
### Configurar o Mapeamento para uma Collection
ABP registra automaticamente entidades MongoDB client library para todas propriedades `IMongoCollection<TEntity>` em seu DbContext. Para o exemplo acima, as entidades `Question` e `Category` são registradas automaticamente.
Para cada entidade registrada, chama `AutoMap()` e configura propriedades conhecidas de sua entidade. Por exemplo, se sua entidade implementa uma interface `IHasExtraProperties` (que já está implementada para cada raiz agregada por padrão), ele configura automaticamente `ExtraProperties`.
Portanto, na maioria das vezes, você não precisa configurar explicitamente o registro de suas entidades. No entanto, se você precisar, pode fazer isso sobrescrevendo o método `CreateModel` em seu DbContext. Exemplo:
````csharp
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.Entity<Question>(b =>
{
b.CollectionName = "MyQuestions"; // Define o nome da collection
b.BsonMap.UnmapProperty(x => x.MyProperty); // Ignora 'MyProperty'
});
}
````
Este exemplo altera o nome da collection mapeada para 'MyQuestions' no banco de dados e ignora uma propriedade na classe `Question`.
Se você só precisa configurar o nome da collection, você também pode usar o atributo `[MongoCollection]` para a collection em seu DbContext. Exemplo:
````csharp
[MongoCollection("MyQuestions")] // Define o nome da collection
public IMongoCollection<Question> Questions => Collection<Question>();
````
### Configurar a Seleção da String de Conexão
Se você tiver vários bancos de dados em seu aplicativo, você pode configurar o nome da string de conexão para o seu DbContext usando o atributo `[ConnectionStringName]`. Exemplo:
````csharp
[ConnectionStringName("MySecondConnString")]
public class MyDbContext : AbpMongoDbContext
{
}
````
Se você não configurar, a string de conexão `Default` é usada. Se você configurar um nome de string de conexão, mas não definir este nome da string de conexão na configuração da aplicação, então ele retorna para a string de conexão `Default`.
## Registrando DbContext para Injeção de Dependência
Use o método `AddAbpDbContext` em seu module para registrar sua classe DbContext para o sistema de [injeção de dependência](Dependency-Injection.md).
```c#
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.MongoDB;
using Volo.Abp.Modularity;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpMongoDbModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<MyDbContext>();
// ...
}
}
}
```
### Adicionar Repositories Padrão
O ABP pode criar automaticamente [repositories genéricas](Repositories.md) padrão para as entidades em seu DbContext. Basta usar a opção `AddDefaultRepositories()` no registro:
````C#
services.AddMongoDbContext<MyDbContext>(options =>
{
options.AddDefaultRepositories();
});
````
Isso criará uma repository para cada [aggregate root entity](Entities.md) (classes derivadas de `AggregateRoot`) por padrão. Se você quiser criar repositories para outras entidades também, em seguida defina `includeAllEntities` para `true`:
```c#
services.AddMongoDbContext<MyDbContext>(options =>
{
options.AddDefaultRepositories(includeAllEntities: true);
});
```
Então você pode injetar e usar `IRepository<TEntity, TPrimaryKey>` nas suas services. Suponha que você tenha uma entidade `Book` com a chave primária `Guid`:
```csharp
public class Book : AggregateRoot<Guid>
{
public string Name { get; set; }
public BookType Type { get; set; }
}
```
(`BookType` é um simples `enum` aqui) E você deseja criar uma nova entidade `Book` em uma [domain service](Domain-Services.md):
```csharp
public class BookManager : DomainService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookManager(IRepository<Book, Guid> bookRepository) // injetar repositório padrão
{
_bookRepository = bookRepository;
}
public async Task<Book> CreateBook(string name, BookType type)
{
Check.NotNullOrWhiteSpace(name, nameof(name));
var book = new Book
{
Id = GuidGenerator.Create(),
Name = name,
Type = type
};
await _bookRepository.InsertAsync(book); // Use um método de repositório padrão
return book;
}
}
```
Este exemplo usa o método `InsertAsync` para inserir uma nova entity no banco de dados.
### Adicionar Repositories Personalizadas
Repositories genéricas padrão são poderosas e suficiente na maioria dos casos (uma vez que implementam `IQueryable`). No entanto, pode ser necessário criar uma repository customizada para adicionar seus próprios métodos de repository.
Suponha que você deseja excluir todos os books por type. É sugerido definir uma interface para sua repository personalizada:
```csharp
public interface IBookRepository : IRepository<Book, Guid>
{
Task DeleteBooksByType(
BookType type,
CancellationToken cancellationToken = default(CancellationToken)
);
}
```
Você geralmente vai querer derivar de `IRepository` para herdar métodos de repository padrão. No entanto, você não precisa. As interfaces de repository são definidas na camada de domínio de uma aplicação em camadas. Elas são implementadas na camada de dados ou infraestrutura (projeto `MongoDB` em um [startup template](https://abp.io/Templates)).
Exemplo de implementação da interface `IBookRepository`:
```csharp
public class BookRepository :
MongoDbRepository<BookStoreMongoDbContext, Book, Guid>,
IBookRepository
{
public BookRepository(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task DeleteBooksByType(
BookType type,
CancellationToken cancellationToken = default(CancellationToken))
{
var collection = await GetCollectionAsync(cancellationToken);
await collection.DeleteManyAsync(
Builders<Book>.Filter.Eq(b => b.Type, type),
cancellationToken
);
}
}
```
Agora é possível [injetar](Dependency-Injection.md) a `IBookRepository` e usar o método `DeleteBooksByType` quando necessário.
#### Substituir Repository Genérica Padrão
Mesmo se você criar uma repository personalizada, você ainda pode injetar a repository genérica padrão (`IRepository<Book, Guid>` para este exemplo). A implementação da repository padrão não usará a classe que você criou.
Se você querer substituir a implementação da repository padrão pela sua repository personalizada, faça dentro das opções `AddMongoDbContext`:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.AddDefaultRepositories();
options.AddRepository<Book, BookRepository>(); //Replaces IRepository<Book, Guid>
});
```
Isso é especialmente importante quando você deseja dar **override em um método da base repository** para customizar. Por exemplo, você pode querer substituir o método `DeleteAsync` para excluir uma entidade de uma forma mais eficiente:
```csharp
public async override Task DeleteAsync(
Guid id,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
// TODO: Implementação customizada do método delete
}
```
### Acesso à API MongoDB
Na maioria dos casos, você vai querer ocultar APIs do MongoDB atrás de uma repository (este é o objetivo principal da repository). No entanto, se você quiser acessar a API MongoDB através da Repository, você pode usar os métodos de extensão `GetDatabaseAsync()`, `GetCollectionAsync()` ou `GetAggregateAsync()`. Exemplo:
```csharp
public class BookService
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookService(IRepository<Book, Guid> bookRepository)
{
_bookRepository = bookRepository;
}
public async Task FooAsync()
{
IMongoDatabase database = await _bookRepository.GetDatabaseAsync();
IMongoCollection<Book> books = await _bookRepository.GetCollectionAsync();
IAggregateFluent<Book> bookAggregate = await _bookRepository.GetAggregateAsync();
}
}
```
> Importante: Você deve fazer referência ao pacote `Volo.Abp.MongoDB` do projeto que deseja acessar a API MongoDB. Isso quebra o encapsulamento, mas é o que você deseja nesse caso.
### Transactions
O MongoDB oferece suporte multi-document transactions a partir da versão 4.0 e o ABP Framework oferece suporte para isso. No entanto, o [startup template](Startup-templates/Index.md) **desativa** transactions por padrão. Se o seu **servidor** MongoDB suportar transactions, você pode habilitar esse recurso na classe *YourProjectMongoDbModule*:
```csharp
Configure<AbpUnitOfWorkDefaultOptions>(options =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto;
});
```
> Ou você pode excluir este código, pois este já é o comportamento padrão.
### Tópicos Avançados
### Controlando o Multi-Tenancy
Se sua solução for [multi-tenant](Multi-Tenancy.md), os tenants podem ter **bancos de dados separados**, você tem **múltiplas** classes `DbContext` em sua solução e algumas de suas classes `DbContext` devem ser utilizáveis **apenas do lado do host**, é recomendado adicionar o atributo `[IgnoreMultiTenancy]` em sua classe `DbContext`. Nesse caso, a ABP garante que o `DbContext` relacionado sempre usa a [connection string](Connection-Strings.md) do host, mesmo se você estiver em um tenant context.
**Exemplo:**
````csharp
[IgnoreMultiTenancy]
public class MyDbContext : AbpMongoDbContext
{
...
}
````
Não use o atributo `[IgnoreMultiTenancy]` se qualquer uma de suas entidades em seu `DbContext` puder ser persistida em um outro banco de dados de um tenant.
> When you use repositories, ABP already uses the host database for the entities don't implement the `IMultiTenant` interface. So, most of time you don't need to `[IgnoreMultiTenancy]` attribute if you are using the repositories to work with the database.
#### Definir Classes Repository Padrão
Repositories genéricas padrão são implementadas pela classe `MongoDbRepository` por padrão. Você pode criar sua própria implementação e usá-la para implementação da repository padrão.
Primeiro, defina suas classes de repository assim:
```csharp
public class MyRepositoryBase<TEntity>
: MongoDbRepository<BookStoreMongoDbContext, TEntity>
where TEntity : class, IEntity
{
public MyRepositoryBase(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
public class MyRepositoryBase<TEntity, TKey>
: MongoDbRepository<BookStoreMongoDbContext, TEntity, TKey>
where TEntity : class, IEntity<TKey>
{
public MyRepositoryBase(IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
```
O primeiro é para [entities com chaves compostas](Entities.md), o segundo é para entities com uma única chave primária.
É sugerido herdar da classe `MongoDbRepository` e substituir os métodos, se necessário. Caso contrário, você terá que implementar todos os métodos de repository padrão manualmente.
Agora, você pode usar a opção `SetDefaultRepositoryClasses`:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.SetDefaultRepositoryClasses(
typeof(MyRepositoryBase<,>),
typeof(MyRepositoryBase<>)
);
// ...
});
```
#### Definir classe base MongoDbContext ou Interface para Repositories padrão
Se seu MongoDbContext herda de outro MongoDbContext ou implementa uma interface, você pode usar essa classe base ou interface como o MongoDbContext para repositories padrão. Exemplo:
```csharp
public interface IBookStoreMongoDbContext : IAbpMongoDbContext
{
Collection<Book> Books { get; }
}
```
`IBookStoreMongoDbContext` é implementado pela classe `BookStoreMongoDbContext`. Então você pode usar sobrecarga genérica do `AddDefaultRepositories`:
```csharp
context.Services.AddMongoDbContext<BookStoreMongoDbContext>(options =>
{
options.AddDefaultRepositories<IBookStoreMongoDbContext>();
// ...
});
```
Agora, seu `BookRepository` personalizado também pode usar a interface `IBookStoreMongoDbContext`:
```csharp
public class BookRepository
: MongoDbRepository<IBookStoreMongoDbContext, Book, Guid>,
IBookRepository
{
// ...
}
```
Uma vantagem de usar a interface para um MongoDbContext é que ela pode ser substituída por outra implementação.
#### Substituir Outros DbContexts
Depois de definir e usar adequadamente uma interface para um MongoDbContext, qualquer outra implementação pode usar as seguintes maneiras de substituí-lo:
**ReplaceDbContextAttribute**
```csharp
[ReplaceDbContext(typeof(IBookStoreMongoDbContext))]
public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext
{
// ...
}
```
**Opção ReplaceDbContext**
```csharp
context.Services.AddMongoDbContext<OtherMongoDbContext>(options =>
{
// ...
options.ReplaceDbContext<IBookStoreMongoDbContext>();
});
```
Neste exemplo, `OtherMongoDbContext` implementa `IBookStoreMongoDbContext`. Este recurso permite que você tenha vários MongoDbContext (um por módulo) no desenvolvimento, mas um único MongoDbContext (implementa todas as interfaces de todos os MongoDbContexts) no tempo de execução.
### Personalizar Operações em Massa
Se você tiver uma lógica melhor ou usar uma biblioteca externa para operações em massa, pode substituir a lógica por meio da implementação de `IMongoDbBulkOperationProvider`.
- Você pode usar o modelo de exemplo abaixo:
```csharp
public class MyCustomMongoDbBulkOperationProvider
: IMongoDbBulkOperationProvider, ITransientDependency
{
public async Task DeleteManyAsync<TEntity>(
IMongoDbRepository<TEntity> repository,
IEnumerable<TEntity> entities,
IClientSessionHandle sessionHandle,
bool autoSave,
CancellationToken cancellationToken)
where TEntity : class, IEntity
{
// Sua lógica aqui.
}
public async Task InsertManyAsync<TEntity>(
IMongoDbRepository<TEntity> repository,
IEnumerable<TEntity> entities,
IClientSessionHandle sessionHandle,
bool autoSave,
CancellationToken cancellationToken)
where TEntity : class, IEntity
{
// Sua lógica aqui.
}
public async Task UpdateManyAsync<TEntity>(
IMongoDbRepository<TEntity> repository,
IEnumerable<TEntity> entities,
IClientSessionHandle sessionHandle,
bool autoSave,
CancellationToken cancellationToken)
where TEntity : class, IEntity
{
// Sua lógica aqui.
}
}
```
## Veja Também
* [Entities](Entities.md)
* [Repositories](Repositories.md)

6
docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md

@ -151,14 +151,14 @@ public class MyDistributedIdentityUserChangeEventHandler :
* 它实现了多个 `IDistributedEventHandler` 接口: **创建**,**更改**和**删除**,因为分布式事件总线单独发布事件,没有本地事件总线那样的"Changed"事件.
* 它订阅了 `EntityEto`, 这是一个通用的事件类,ABP框架针对所有类型的实体**自动发布**. 这就是为什么它检查**实体类型**(因为我们没有假设有对 `IdentityUser` 实体有安全的类型引用,所以它是字符串类型的).
预构建应用模块没有定义专门的事件类型(如`IdentityUserEto` - "ETO" 意思是 "事件传输对象"). 此功能在路线图上([关注这个issue](https://github.com/abpframework/abp/issues/3033)),一旦完成后,你就可以订阅独立的实体类型:
预构建应用模块没有定义专门的事件类型(如`UserEto` - "ETO" 意思是 "事件传输对象"). 此功能在路线图上([关注这个issue](https://github.com/abpframework/abp/issues/3033)),一旦完成后,你就可以订阅独立的实体类型:
````csharp
public class MyDistributedIdentityUserCreatedEventHandler :
IDistributedEventHandler<EntityCreatedEto<IdentityUserEto>>,
IDistributedEventHandler<EntityCreatedEto<UserEto>>,
ITransientDependency
{
public async Task HandleEventAsync(EntityCreatedEto<IdentityUserEto> eventData)
public async Task HandleEventAsync(EntityCreatedEto<UserEto> eventData)
{
var userId = eventData.Entity.Id;
var userName = eventData.Entity.UserName;

55
docs/zh-Hans/Distributed-Event-Bus.md

@ -4,7 +4,7 @@
## 提供程序
分布式事件总线系统提供了一个可以被任何提供程序实现的**抽象**. 有两种开箱即用的提供程序:
分布式事件总线系统提供了一个可以被任何提供程序实现的**抽象**. 有四种开箱即用的提供程序:
* `LocalDistributedEventBus` 是默认实现,实现作为进程内工作的分布式事件总线. 是的!如果没有配置真正的分布式提供程序,**默认实现的工作方式与[本地事件总线](Local-Event-Bus.md)一样**.
* `RabbitMqDistributedEventBus` 通过[RabbitMQ](https://www.rabbitmq.com/)实现分布式事件总线. 请参阅[RabbitMQ集成文档](Distributed-Event-Bus-RabbitMQ-Integration.md)了解如何配置它.
@ -299,4 +299,55 @@ namespace AbpDemo
}
````
此示例使用AutoMapper的 `AutoMap` 属性配置的映射. 你可以创建一个配置文件类代替. 请参阅AutoMapper文档了解更多选项.
此示例使用AutoMapper的 `AutoMap` 属性配置的映射. 你可以创建一个配置文件类代替. 请参阅AutoMapper文档了解更多选项.
## 异常处理
ABP提供了异常处理, 它会进行重试并且重试失败后移动到死信队列.
启用异常处理:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.EnabledErrorHandle = true;
options.UseRetryStrategy();
});
}
```
* `EnabledErrorHandle` 用于启用异常处理.
* `UseRetryStrategy` 用于启用重试.
当一个异常抛出,它会每3秒重试一次直到最大重试次数(默认是3)并且移动到错误队列, 你可以更改重试次数,重试间隔和死信队列名称:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.DeadLetterName = "dead_queue";
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### 错误处理选择器
默认所有的事件类型都会被处理, 你可以使用 `AbpEventBusOptions` 的 `ErrorHandleSelector` 来更改它:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` 实际上是一个类型类型谓词列表. 你可以编写lambda来定义你的过滤.
### 自定义异常处理
ABP定义了 `IEventErrorHandler` 接口并且由提供程序实现, 你可以通过[依赖注入](Dependency-Injection.md)替换它.

283
docs/zh-Hans/Entity-Framework-Core.md

@ -30,7 +30,7 @@ namespace MyCompany.MyProject
### 数据库管理系统选择
EF Core支持多种数据库管理系统([查看全部](https://docs.microsoft.com/en-us/ef/core/providers/)). ABP框架和本文档不依赖于任何特定的DBMS.
EF Core支持多种数据库管理系统([查看全部](https://docs.microsoft.com/zh-cn/ef/core/providers/)). ABP框架和本文档不依赖于任何特定的DBMS.
如果要创建一个可重用的[应用程序模块](Modules/Index.md),应避免依赖于特定的DBMS包.但在最终的应用程序中,始终会选择一个DBMS.
@ -60,7 +60,7 @@ namespace MyCompany.MyProject
### 关于EF Core Fluent Mapping
[应用程序启动模板](Startup-Templates/Application.md)已配置使用[EF Core fluent configuration API](https://docs.microsoft.com/en-us/ef/core/modeling/)映射你的实体到数据库表.
[应用程序启动模板](Startup-Templates/Application.md)已配置使用[EF Core fluent configuration API](https://docs.microsoft.com/zh-cn/ef/core/modeling/)映射你的实体到数据库表.
你依然为你的实体属性使用**data annotation attributes**(像`[Required]`),而ABP文档通常遵循**fluent mapping API** approach方法. 如何使用取决与你.
@ -272,6 +272,285 @@ public async override Task DeleteAsync(
}
````
## 加载关联实体
假设你拥有带有`OrderLine`集合的`Order`,并且`OrderLine`具有`Order`的导航属性:
````csharp
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
namespace MyCrm
{
public class Order : AggregateRoot<Guid>, IHasCreationTime
{
public Guid CustomerId { get; set; }
public DateTime CreationTime { get; set; }
public ICollection<OrderLine> Lines { get; set; } //子集合
public Order()
{
Lines = new Collection<OrderLine>();
}
}
public class OrderLine : Entity<Guid>
{
public Order Order { get; set; } //导航属性
public Guid OrderId { get; set; }
public Guid ProductId { get; set; }
public int Count { get; set; }
public double UnitPrice { get; set; }
}
}
````
然后象下面显示的这样定义数据库映射:
````csharp
builder.Entity<Order>(b =>
{
b.ToTable("Orders");
b.ConfigureByConvention();
//定义关系
b.HasMany(x => x.Lines)
.WithOne(x => x.Order)
.HasForeignKey(x => x.OrderId)
.IsRequired();
});
builder.Entity<OrderLine>(b =>
{
b.ToTable("OrderLines");
b.ConfigureByConvention();
});
````
当你查询一个 `Order`, 你可能想要在单个查询中**包含**所有的 `OrderLine`s 或根据需要在**以后加载它们**.
> 实际上这与ABP框架没有直接关系. 你可以按照 [EF Core 文档](https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/) 了解全部细节. 本节将涵盖与 ABP 框架相关的一些主题.
### 预先加载 / 包含子对象的加载
当你想加载一个带有关联实体的实体时,可以使用不同的选项.
#### Repository.WithDetails
`IRepository.WithDetailsAsync(...)` 可以通过包含一个关系收集/属性来获得 `IQueryable<T>` .
**示例: 获取一个带有 `lines` 的 `order` 对象**
````csharp
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
namespace AbpDemo.Orders
{
public class OrderManager : DomainService
{
private readonly IRepository<Order, Guid> _orderRepository;
public OrderManager(IRepository<Order, Guid> orderRepository)
{
_orderRepository = orderRepository;
}
public async Task TestWithDetails(Guid id)
{
//通过包含子集合获取一个 IQueryable<T>
var queryable = await _orderRepository.WithDetailsAsync(x => x.Lines);
//应用其他的 LINQ 扩展方法
var query = queryable.Where(x => x.Id == id);
//执行此查询并获取结果
var order = await AsyncExecuter.FirstOrDefaultAsync(query);
}
}
}
````
> `AsyncExecuter` 用于执行异步 LINQ 扩展,而无需依赖 EF Core. 如果你将 EF Core NuGet 包引用添加到你的项目中,则可以直接使用 `await query.FirstOrDefaultAsync()`. 但是, 这次你依赖于域层中的 EF 核心.请参阅. 请参阅 [仓储文档](Repositories.md) 以了解更多.
**示例: 获取一个包含 `lines` 的 `orders` 列表**
````csharp
public async Task TestWithDetails()
{
//通过包含一个子集合获取一个 IQueryable<T>
var queryable = await _orderRepository.WithDetailsAsync(x => x.Lines);
//执行此查询并获取结果
var orders = await AsyncExecuter.ToListAsync(queryable);
}
````
> 如果你需要包含多个导航属性或集合,`WithDetailsAsync`方法可以获得多个表达参数.
#### DefaultWithDetailsFunc
如果你没有将任何表达式传递到 `WithDetailsAsync` 方法,则它包括使用你提供的 `DefaultWithDetailsFunc` 选项的所有详细信息.
你可以在你的 `EntityFrameworkCore` 项目[模块](Module-Development-Basics.md)的 `ConfigureServices`方法为一个实体配置 `DefaultWithDetailsFunc`.
**示例: 在查询一个 `Order` 时包含 `Lines`**
````csharp
Configure<AbpEntityOptions>(options =>
{
options.Entity<Order>(orderOptions =>
{
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Lines);
});
});
````
> 你可以在这里完全使用 EF Core API,因为这位于 EF Core集成项目中.
然后你可以不带任何参数地调用 `WithDetails` 方法:
````csharp
public async Task TestWithDetails()
{
//通过包含一个子集合获取一个 IQueryable<T>
var queryable = await _orderRepository.WithDetailsAsync();
//执行此查询并获取结果
var orders = await AsyncExecuter.ToListAsync(queryable);
}
````
`WithDetailsAsync()` 执行你已经在 `DefaultWithDetailsFunc` 中设置的表达式.
#### 仓储 Get/Find 方法
有些标准的 [仓储](Repositories.md) 方法带有可选的 `includeDetails` 参数;
* `GetAsync` 和 `FindAsync` 方法带有默认值为 `true` 的 `includeDetails`.
* `GetListAsync` 和 `GetPagedListAsync` 方法带有默认值为 `false` 的 `includeDetails`.
这意味着,默认情况下返回**包含子对象的单个实体**,而列表返回方法则默认不包括子对象信息.你可以明确通过 `includeDetails` 来更改此行为.
> 这些方法使用上面解释的 `DefaultWithDetailsFunc` 选项.
**示例:获取一个包含子对象的 `order`**
````csharp
public async Task TestWithDetails(Guid id)
{
var order = await _orderRepository.GetAsync(id);
}
````
**示例:获取一个不包含子对象的 `order`**
````csharp
public async Task TestWithoutDetails(Guid id)
{
var order = await _orderRepository.GetAsync(id, includeDetails: false);
}
````
**示例:获取一个包含子对象的实体列表**
````csharp
public async Task TestWithDetails()
{
var orders = await _orderRepository.GetListAsync(includeDetails: true);
}
````
#### 选择
存储库模式尝试封装 EF Core, 因此你的选项是有限的. 如果你需要高级方案,你可以按照其中一个选项执行:
* 创建自定义存储库方法并使用完整的 EF Core API.
* 在你的项目中引用 `Volo.Abp.EntityFrameworkCore` . 通过这种方式,你可以直接在代码中使用 `Include` 和 `ThenInclude` .
请参阅 EF Core 的 [预先加载文档](https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/eager).
### 显示 / 延迟加载
如果你在查询实体时不包括关系,并且以后需要访问导航属性或集合,则你有不同的选择.
#### EnsurePropertyLoadedAsync / EnsureCollectionLoadedAsync
仓储提供 `EnsurePropertyLoadedAsync` 和 `EnsureCollectionLoadedAsync` 扩展方法来**显示加载**一个导航属性或子集合.
**示例: 在需要时加载一个 `Order` 的 `Lines`**
````csharp
public async Task TestWithDetails(Guid id)
{
var order = await _orderRepository.GetAsync(id, includeDetails: false);
//order.Lines 此时是空的
await _orderRepository.EnsureCollectionLoadedAsync(order, x => x.Lines);
//order.Lines 被填充
}
````
如果导航属性或集合已经被加载那么 `EnsurePropertyLoadedAsync` 和 `EnsureCollectionLoadedAsync` 方法不做任何处理. 所以,调用多次也没有问题.
请参阅 EF Core 的[显示加载文档](https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/explicit).
#### 使用代理的延时加载
在某些情况下,可能无法使用显示加载,尤其是当你没有引用 `Repository` 或 `DbContext`时.延时加载是 EF Core 加载关联属性/集合的一个功能,,当你第一次访问它.
启用延时加载:
1. 安装 [Microsoft.EntityFrameworkCore.Proxies](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Proxies/) 包到你的项目(通常是 EF Core 集成项目)
2. 为你的 `DbContext` 配置 `UseLazyLoadingProxies` (在 EF Core 项目的模块的 `ConfigureServices` 方法中). 例如:
````csharp
Configure<AbpDbContextOptions>(options =>
{
options.PreConfigure<MyCrmDbContext>(opts =>
{
opts.DbContextOptions.UseLazyLoadingProxies(); //启用延时加载
});
options.UseSqlServer();
});
````
3. 使你的导航属性和集合是 `virtual`. 例如:
````csharp
public virtual ICollection<OrderLine> Lines { get; set; } //虚集合
public virtual Order Order { get; set; } //虚导航属性
````
启用延时加载并整理实体后,你可以自由访问导航属性和集合:
````csharp
public async Task TestWithDetails(Guid id)
{
var order = await _orderRepository.GetAsync(id);
//order.Lines 此时是空的
var lines = order.Lines;
//order.Lines 被填充 (延时加载)
}
````
每当你访问属性/集合时,EF Core 都会自动执行额外的查询,从数据库中加载属性/集合.
> 应谨慎使用延时加载,因为它可能会在某些特定情况下导致性能问题.
请参阅 EF Core 的[延时加载文档](https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/lazy).
## 访问 EF Core API
大多数情况下应该隐藏仓储后面的EF Core API(这也是仓储的设计目地). 但是如果想要通过仓储访问DbContext实现,则可以使用`GetDbContext()`或`GetDbSet()`扩展方法. 例:

48
docs/zh-Hans/Local-Event-Bus.md

@ -158,7 +158,53 @@ namespace AbpDemo
如果您执行**数据库操作**并在事件处理程序中使用[仓储](Repositories.md),那么您可能需要创建一个[工作单元](Unit-Of-Work.md),因为一些存储库方法需要在**活动的工作单元**中工作. 确保处理方法设置为 `virtual`,并为该方法添加一个 `[UnitOfWork]` attribute. 或者手动使用 `IUnitOfWorkManager` 创建一个工作单元范围.
## 事务和异常行为
## 异常处理
ABP提供了异常处理, 当异常发现时它会进行重试.
启用异常处理:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy();
});
}
```
当一个异常抛出,它会每3秒重试一次直到最大重试次数(默认是3)并且移动抛出原始异常, 你可以更改重试次数和重试间隔和:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### 错误处理选择器
默认所有的事件类型都会被处理, 你可以使用 `AbpEventBusOptions` 的 `ErrorHandleSelector` 来更改它:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` 实际上是一个类型类型谓词列表. 你可以编写lambda来定义你的过滤.
### 自定义异常处理
ABP定义了 `IEventErrorHandler` 接口并且由 `LocalEventErrorHandler` 实现, 你可以通过[依赖注入](Dependency-Injection.md)替换它.
### 事务和异常行为
当一个事件发布,订阅的事件处理程序将立即执行.所以;

2
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo.Abp.AspNetCore.Components.Server.csproj

@ -12,6 +12,8 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web\Volo.Abp.AspNetCore.Components.Web.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.SignalR\Volo.Abp.AspNetCore.SignalR.csproj" />
</ItemGroup>

6
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs

@ -5,8 +5,10 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.EventBus;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
@ -15,7 +17,9 @@ namespace Volo.Abp.AspNetCore.Components.Server
[DependsOn(
typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreComponentsWebModule),
typeof(AbpAspNetCoreSignalRModule)
typeof(AbpAspNetCoreSignalRModule),
typeof(AbpEventBusModule),
typeof(AbpAspNetCoreMvcContractsModule)
)]
public class AbpAspNetCoreComponentsServerModule : AbpModule
{

29
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs

@ -0,0 +1,29 @@
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Local;
namespace Volo.Abp.AspNetCore.Components.Server.Configuration
{
[Dependency(ReplaceServices = true)]
public class BlazorServerCurrentApplicationConfigurationCacheResetService :
ICurrentApplicationConfigurationCacheResetService,
ITransientDependency
{
private readonly ILocalEventBus _localEventBus;
public BlazorServerCurrentApplicationConfigurationCacheResetService(
ILocalEventBus localEventBus)
{
_localEventBus = localEventBus;
}
public async Task ResetAsync()
{
await _localEventBus.PublishAsync(
new CurrentApplicationConfigurationCacheResetEventData()
);
}
}
}

9
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web.Configuration
{
public interface ICurrentApplicationConfigurationCacheResetService
{
Task ResetAsync();
}
}

13
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs

@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Configuration
{
public class NullCurrentApplicationConfigurationCacheResetService : ICurrentApplicationConfigurationCacheResetService, ISingletonDependency
{
public Task ResetAsync()
{
return Task.CompletedTask;
}
}
}

32
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs

@ -0,0 +1,32 @@
using System;
using Microsoft.AspNetCore.Http;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
public static class AbpMultiTenancyCookieHelper
{
public static void SetTenantCookie(
HttpContext context,
Guid? tenantId,
string tenantKey)
{
if (tenantId != null)
{
context.Response.Cookies.Append(
tenantKey,
tenantId.ToString(),
new CookieOptions
{
Path = "/",
HttpOnly = false,
Expires = DateTimeOffset.Now.AddYears(10)
}
);
}
else
{
context.Response.Cookies.Delete(tenantKey);
}
}
}
}

14
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs

@ -1,9 +1,6 @@
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.RequestLocalization;
@ -21,14 +18,17 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantConfigurationProvider _tenantConfigurationProvider;
private readonly ICurrentTenant _currentTenant;
private readonly AbpAspNetCoreMultiTenancyOptions _options;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware(
ITenantConfigurationProvider tenantConfigurationProvider,
ICurrentTenant currentTenant,
IOptions<AbpAspNetCoreMultiTenancyOptions> options)
IOptions<AbpAspNetCoreMultiTenancyOptions> options,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{
_tenantConfigurationProvider = tenantConfigurationProvider;
_currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
_options = options.Value;
}
@ -49,6 +49,12 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{
using (_currentTenant.Change(tenant?.Id, tenant?.Name))
{
if (_tenantResolveResultAccessor.Result != null &&
_tenantResolveResultAccessor.Result.AppliedResolvers.Contains(QueryStringTenantResolveContributor.ContributorName))
{
AbpMultiTenancyCookieHelper.SetTenantCookie(context, _currentTenant.Id, _options.TenantKey);
}
var requestCulture = await TryGetRequestCultureAsync(context);
if (requestCulture != null)
{

23
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Volo.Abp.MultiTenancy;
@ -12,9 +13,23 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
protected override Task<string> GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext)
{
return Task.FromResult(httpContext.Request.QueryString.HasValue
? httpContext.Request.Query[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey].ToString()
: null);
if (httpContext.Request.QueryString.HasValue)
{
var tenantKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey;
if (httpContext.Request.Query.ContainsKey(tenantKey))
{
var tenantValue = httpContext.Request.Query[tenantKey].ToString();
if (tenantValue.IsNullOrWhiteSpace())
{
context.Handled = true;
return Task.FromResult<string>(null);
}
return Task.FromResult(tenantValue);
}
}
return Task.FromResult<string>(null);
}
}
}

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

@ -41,11 +41,8 @@ namespace Pages.Abp.MultiTenancy
public async Task OnPostAsync()
{
if (Input.Name.IsNullOrEmpty())
{
Response.Cookies.Delete(Options.TenantKey);
}
else
Guid? tenantId = null;
if (!Input.Name.IsNullOrEmpty())
{
var tenant = await TenantStore.FindAsync(Input.Name);
if (tenant == null)
@ -58,17 +55,10 @@ namespace Pages.Abp.MultiTenancy
throw new UserFriendlyException(L["GivenTenantIsNotAvailable", Input.Name]);
}
Response.Cookies.Append(
Options.TenantKey,
tenant.Id.ToString(),
new CookieOptions
{
Path = "/",
HttpOnly = false,
Expires = DateTimeOffset.Now.AddYears(10)
}
);
tenantId = tenant.Id;
}
AbpMultiTenancyCookieHelper.SetTenantCookie(HttpContext, tenantId, Options.TenantKey);
}
public class TenantInfoModel

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sk.json

@ -0,0 +1,12 @@
{
"culture": "sk",
"texts": {
"GivenTenantIsNotAvailable": "Daný tenant nie je k dispozícii: {0}",
"Tenant": "Tenant",
"Switch": "prepnúť",
"Name": "Meno",
"SwitchTenantHint": "Ak sa chcete prihlásiť ako používateľ poskytovateľa, nechajte pole s menom prázdne.",
"SwitchTenant": "Prepnúť tenanta",
"NotSelected": "Nie je vybraný"
}
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs

@ -16,18 +16,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/to-mark/to-mark.min.js");
if (context.FileProvider.GetFileInfo("/libs/tui-code-snippet/tui-code-snippet.min.js").Exists)
{
context.Files.AddIfNotContains("/libs/tui-code-snippet/tui-code-snippet.min.js");
}
else
{
context.Files.AddIfNotContains("/libs/tui-code-snippet/tui-code-snippet.js");
}
context.Files.AddIfNotContains("/libs/squire-rte/squire.js");
context.Files.AddIfNotContains("/libs/tui-editor/toastui-editor.js");
}
}

26
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpDataAnnotationAutoLocalizationMetadataDetailsProvider.cs

@ -54,7 +54,29 @@ namespace Volo.Abp.AspNetCore.Mvc
displayMetadata.DisplayName = () =>
{
var localizedString = localizer[PropertyLocalizationKeyPrefix + context.Key.Name];
/*
* DisplayName:ClassName:PropertyName
* DisplayName:PropertyName
* ClassName:PropertyName
* PropertyName
*/
LocalizedString localizedString = null;
if (context.Key.ContainerType != null)
{
localizedString = localizer[PropertyLocalizationKeyPrefix + context.Key.ContainerType.Name + ":" + context.Key.Name];
}
if (localizedString == null || localizedString.ResourceNotFound)
{
localizedString = localizer[PropertyLocalizationKeyPrefix + context.Key.Name];
}
if (localizedString.ResourceNotFound && context.Key.ContainerType != null)
{
localizedString = localizer[context.Key.ContainerType.Name + ":" + context.Key.Name];
}
if (localizedString.ResourceNotFound)
{
@ -65,4 +87,4 @@ namespace Volo.Abp.AspNetCore.Mvc
};
}
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs

@ -110,7 +110,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
{
postedFiles.Add(new RemoteStreamContent(file.OpenReadStream())
{
ContentType = file.ContentType
ContentType = file.ContentType,
FileName = file.FileName
});
}
}

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs

@ -26,6 +26,13 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
{
context.HttpContext.Response.ContentType = remoteStream.ContentType;
if (!remoteStream.FileName.IsNullOrWhiteSpace())
{
var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName(remoteStream.FileName);
context.HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
}
using (var stream = remoteStream.GetStream())
{
if (stream.CanSeek)

33
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpAspNetCoreMvcQueryStringCultureReplacement.cs

@ -0,0 +1,33 @@
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.Localization
{
public class AbpAspNetCoreMvcQueryStringCultureReplacement : IQueryStringCultureReplacement, ITransientDependency
{
public virtual Task ReplaceAsync(QueryStringCultureReplacementContext context)
{
if (!string.IsNullOrWhiteSpace(context.ReturnUrl))
{
if (context.ReturnUrl.Contains("culture=", StringComparison.OrdinalIgnoreCase) &&
context.ReturnUrl.Contains("ui-Culture=", StringComparison.OrdinalIgnoreCase))
{
context.ReturnUrl = Regex.Replace(
context.ReturnUrl,
"culture=[A-Za-z-]+?&",
$"culture={context.RequestCulture.Culture}&",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
context.ReturnUrl = Regex.Replace(
context.ReturnUrl, "ui-culture=[A-Za-z-]+?$",
$"ui-culture={context.RequestCulture.UICulture}",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
}
return Task.CompletedTask;
}
}
}

19
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.RequestLocalization;
using Volo.Abp.Localization;
@ -12,8 +13,15 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization
[ApiExplorerSettings(IgnoreApi = true)]
public class AbpLanguagesController : AbpController
{
protected IQueryStringCultureReplacement QueryStringCultureReplacement { get; }
public AbpLanguagesController(IQueryStringCultureReplacement queryStringCultureReplacement)
{
QueryStringCultureReplacement = queryStringCultureReplacement;
}
[HttpGet]
public IActionResult Switch(string culture, string uiCulture = "", string returnUrl = "")
public virtual async Task<IActionResult> Switch(string culture, string uiCulture = "", string returnUrl = "")
{
if (!CultureHelper.IsValidCultureCode(culture))
{
@ -25,15 +33,18 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization
new RequestCulture(culture, uiCulture)
);
if (!string.IsNullOrWhiteSpace(returnUrl))
var context = new QueryStringCultureReplacementContext(HttpContext, new RequestCulture(culture, uiCulture), returnUrl);
await QueryStringCultureReplacement.ReplaceAsync(context);
if (!string.IsNullOrWhiteSpace(context.ReturnUrl))
{
return Redirect(GetRedirectUrl(returnUrl));
return Redirect(GetRedirectUrl(context.ReturnUrl));
}
return Redirect("~/");
}
private string GetRedirectUrl(string returnUrl)
protected virtual string GetRedirectUrl(string returnUrl)
{
if (returnUrl.IsNullOrEmpty())
{

9
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/IQueryStringCultureReplacement.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Mvc.Localization
{
public interface IQueryStringCultureReplacement
{
Task ReplaceAsync(QueryStringCultureReplacementContext context);
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/QueryStringCultureReplacementContext.cs

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Localization
{
public class QueryStringCultureReplacementContext
{
public HttpContext HttpContext { get; }
public RequestCulture RequestCulture { get; }
public string ReturnUrl { get; set; }
public QueryStringCultureReplacementContext(HttpContext httpContext, RequestCulture requestCulture, string returnUrl)
{
HttpContext = httpContext;
RequestCulture = requestCulture;
ReturnUrl = returnUrl;
}
}
}

10
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/sk.json

@ -0,0 +1,10 @@
{
"culture": "sk",
"texts": {
"Volo.Authorization:010001": "Autorizácia zlyhala! Daná politika nebola udelená.",
"Volo.Authorization:010002": "Autorizácia zlyhala! Daná politika nebola udelená: {PolicyName}",
"Volo.Authorization:010003": "Autorizácia zlyhala! Politika nebola udelená danému zdroju: {ResourceName}",
"Volo.Authorization:010004": "Autorizácia zlyhala! Daná požiadavka nebola udelená danému zdroju: {ResourceName}",
"Volo.Authorization:010005": "Autorizácia zlyhala! Dané požiadavky neboli udelené danému zdroju: {ResourceName}"
}
}

8
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -494,17 +494,17 @@ namespace Volo.Abp.BlazoriseUI
await HandleErrorAsync(ex);
}
}
protected virtual Task OnDeletingEntityAsync()
{
return Task.CompletedTask;
}
protected virtual async Task OnDeletedEntityAsync()
{
await GetEntitiesAsync();
await InvokeAsync(StateHasChanged);
}
}
protected virtual string GetDeleteConfirmationMessage(TListViewModel entity)
{
@ -596,7 +596,7 @@ namespace Volo.Abp.BlazoriseUI
if (propertyInfo.Type.IsEnum)
{
column.ValueConverter = (val) =>
EnumHelper.GetLocalizedMemberName(propertyInfo.Type, val, StringLocalizerFactory);
EnumHelper.GetLocalizedMemberName(propertyInfo.Type, val.As<ExtensibleObject>().ExtraProperties[propertyInfo.Name], StringLocalizerFactory);
}
yield return column;

14
framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor

@ -10,6 +10,20 @@
ShowPager="@ShowPager"
CurrentPage="@CurrentPage"
PageSize="@PageSize">
<LoadingTemplate>
<Row Class="w-100 align-items-center" Style="height: 150px;">
<Column>
<RadarSpinner />
</Column>
</Row>
</LoadingTemplate>
<EmptyTemplate>
<Row Class="w-100 align-items-center" Style="height: 150px;">
<Column>
<Heading Size="HeadingSize.Is4" Alignment="TextAlignment.Center">No data available</Heading>
</Column>
</Row>
</EmptyTemplate>
<DataGridColumns>
@if (Columns != null)
{

27
framework/src/Volo.Abp.BlazoriseUI/Components/RadarSpinner.razor

@ -0,0 +1,27 @@
<div class="d-flex justify-content-center">
<div class="radar-spinner">
<div class="circle">
<div class="circle-inner-container">
<div class="circle-inner"></div>
</div>
</div>
<div class="circle">
<div class="circle-inner-container">
<div class="circle-inner"></div>
</div>
</div>
<div class="circle">
<div class="circle-inner-container">
<div class="circle-inner"></div>
</div>
</div>
<div class="circle">
<div class="circle-inner-container">
<div class="circle-inner"></div>
</div>
</div>
</div>
</div>

8
framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

@ -14,10 +14,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="0.9.3.5" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.3.5" />
<PackageReference Include="Blazorise.Snackbar" Version="0.9.3.5" />
<PackageReference Include="Blazorise.Components" Version="0.9.3.5" />
<PackageReference Include="Blazorise" Version="0.9.3.6" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.3.6" />
<PackageReference Include="Blazorise.Snackbar" Version="0.9.3.6" />
<PackageReference Include="Blazorise.Components" Version="0.9.3.6" />
</ItemGroup>
</Project>

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs

@ -12,5 +12,10 @@ namespace Volo.Abp.Cli.Commands
: base(cliService)
{
}
public override string GetShortDescription()
{
return "Generates Angular service proxies and DTOs to consume HTTP APIs.";
}
}
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProxyCommandBase.cs

@ -140,10 +140,7 @@ namespace Volo.Abp.Cli.Commands
return sb.ToString();
}
public string GetShortDescription()
{
return "Generates Angular service proxies and DTOs to consume HTTP APIs.";
}
public abstract string GetShortDescription();
public static class Options
{

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/RemoveProxyCommand.cs

@ -12,5 +12,10 @@
: base(cliService)
{
}
public override string GetShortDescription()
{
return "Remove Angular service proxies and DTOs to consume HTTP APIs.";
}
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs

@ -10,7 +10,6 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new CreateAppSettingsSecretsStep());
pipeline.Steps.Add(new ProjectReferenceReplaceStep());
pipeline.Steps.Add(new ReplaceCommonPropsStep());
pipeline.Steps.Add(new ReplaceConfigureAwaitPropsStep());

26
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs

@ -1,11 +1,19 @@
using System;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectBuilding.Templates.App;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
public class DatabaseManagementSystemChangeStep : ProjectBuildPipelineStep
{
private readonly bool _hasDbMigrations;
public DatabaseManagementSystemChangeStep(bool hasDbMigrations)
{
_hasDbMigrations = hasDbMigrations;
}
public override void Execute(ProjectBuildContext context)
{
switch (context.BuildArgs.DatabaseManagementSystem)
@ -55,19 +63,19 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private void AdjustOracleDbContextOptionsBuilder(ProjectBuildContext context)
{
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile?.ReplaceText("new DbContextOptionsBuilder",
$"(DbContextOptionsBuilder<{context.BuildArgs.SolutionName.ProjectName}MigrationsDbContext>) new DbContextOptionsBuilder");
$"(DbContextOptionsBuilder<{context.BuildArgs.SolutionName.ProjectName}{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContext>) new DbContextOptionsBuilder");
}
private void AddMySqlServerVersion(ProjectBuildContext context)
{
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile.ReplaceText("configuration.GetConnectionString(\"Default\")",
dbContextFactoryFile?.ReplaceText("configuration.GetConnectionString(\"Default\")",
"configuration.GetConnectionString(\"Default\"), MySqlServerVersion.LatestSupportedServerVersion");
}
@ -93,9 +101,9 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase));
efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethodForEfModule);
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MigrationsDbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.First(f => f.Name.EndsWith("MigrationsDbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile.ReplaceText(oldUseMethod, newUseMethodForDbContext);
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))
?? context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactory.cs", StringComparison.OrdinalIgnoreCase));
dbContextFactoryFile?.ReplaceText(oldUseMethod, newUseMethodForDbContext);
}
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs

@ -78,11 +78,13 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder, _companyName);
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToCamelCase(), _companyName.ToCamelCase());
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToKebabCase(), _companyName.ToKebabCase());
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToLowerInvariant(), _companyName.ToLowerInvariant());
}
else
{
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder + "." + _projectNamePlaceHolder, _projectNamePlaceHolder);
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToCamelCase() + "." + _projectNamePlaceHolder.ToCamelCase(), _projectNamePlaceHolder.ToCamelCase());
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToLowerInvariant() + "." + _projectNamePlaceHolder.ToLowerInvariant(), _projectNamePlaceHolder.ToLowerInvariant());
RenameHelper.RenameAll(_entries, _companyNamePlaceHolder.ToKebabCase() + "/" + _projectNamePlaceHolder.ToKebabCase(), _projectNamePlaceHolder.ToKebabCase());
}
}
@ -90,6 +92,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder, _projectName);
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToCamelCase(), _projectName.ToCamelCase());
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToKebabCase(), _projectName.ToKebabCase());
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToLowerInvariant(), _projectName.ToLowerInvariant());
RenameHelper.RenameAll(_entries, _projectNamePlaceHolder.ToSnakeCase().ToUpper(), _projectName.ToSnakeCase().ToUpper());
}
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -1,4 +1,5 @@
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
using System;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Templates.App;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule;
@ -31,7 +32,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
if (context.Template.Name == AppTemplate.TemplateName ||
context.Template.Name == AppProTemplate.TemplateName)
{
pipeline.Steps.Add(new DatabaseManagementSystemChangeStep()); // todo: move to custom steps?
pipeline.Steps.Add(new DatabaseManagementSystemChangeStep(context.Template.As<AppTemplateBase>().HasDbMigrations)); // todo: move to custom steps?
}
if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor || context.BuildArgs.UiFramework == UiFramework.BlazorServer)

2
framework/src/Volo.Abp.Core/Volo/Abp/Content/IRemoteStreamContent.cs

@ -8,6 +8,8 @@ namespace Volo.Abp.Content
long? ContentLength { get; }
string FileName { get; }
Stream GetStream();
}
}

11
framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs

@ -11,9 +11,18 @@ namespace Volo.Abp.Content
_stream = stream;
}
public RemoteStreamContent(Stream stream, string fileName)
: this(stream)
{
FileName = fileName;
ContentType = "application/octet-stream";
}
public virtual string ContentType { get; set; }
public virtual long? ContentLength => _stream.Length;
public virtual long? ContentLength => GetStream().Length;
public virtual string FileName { get; set; }
public virtual Stream GetStream()
{

6
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/sk.json

@ -0,0 +1,6 @@
{
"culture": "sk",
"texts": {
"MaxResultCountExceededExceptionMessage": "{0} nemôže byť viac ako {1}! Zvýšte {2}.{3} na strane servera, aby ste zobrazili viac výsledkov."
}
}

31
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorListExtensions.cs

@ -26,7 +26,7 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
)
);
}
/// <summary>
/// Adds a specific entity type and the types derived from that entity type.
/// </summary>
@ -49,14 +49,27 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
)
);
}
/// <summary>
/// Remove a specific entity type and the types derived from that entity type.
/// </summary>
/// <typeparam name="TEntity">Type of the entity</typeparam>
public static void Remove<TEntity>([NotNull] this IAutoEntityDistributedEventSelectorList selectors)
where TEntity : IEntity
{
Check.NotNull(selectors, nameof(selectors));
var selectorName = "Entity:" + typeof(TEntity).FullName;
selectors.RemoveAll(s => s.Name == selectorName);
}
/// <summary>
/// Adds all entity types.
/// </summary>
public static void AddAll([NotNull] this IAutoEntityDistributedEventSelectorList selectors)
{
Check.NotNull(selectors, nameof(selectors));
if (selectors.Any(s => s.Name == AllEntitiesSelectorName))
{
return;
@ -72,11 +85,11 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
public static void Add(
[NotNull] this IAutoEntityDistributedEventSelectorList selectors,
string selectorName,
string selectorName,
Func<Type, bool> predicate)
{
Check.NotNull(selectors, nameof(selectors));
if (selectors.Any(s => s.Name == selectorName))
{
throw new AbpException($"There is already a selector added before with the same name: {selectorName}");
@ -89,7 +102,7 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
)
);
}
public static void Add(
[NotNull] this IAutoEntityDistributedEventSelectorList selectors,
Func<Type, bool> predicate)
@ -103,15 +116,15 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
{
Check.NotNull(selectors, nameof(selectors));
Check.NotNull(name, nameof(name));
return selectors.RemoveAll(s => s.Name == name).Count > 0;
}
public static bool IsMatch([NotNull] this IAutoEntityDistributedEventSelectorList selectors, Type entityType)
{
Check.NotNull(selectors, nameof(selectors));
return selectors.Any(s => s.Predicate(entityType));
}
}
}
}

25
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/sk.json

@ -0,0 +1,25 @@
{
"culture": "sk",
"texts": {
"DisplayName:Abp.Mailing.DefaultFromAddress": "Predvolená adresa Od",
"DisplayName:Abp.Mailing.DefaultFromDisplayName": "Predvolené meno Od",
"DisplayName:Abp.Mailing.Smtp.Host": "Host server",
"DisplayName:Abp.Mailing.Smtp.Port": "Port",
"DisplayName:Abp.Mailing.Smtp.UserName": "Meno používateľa",
"DisplayName:Abp.Mailing.Smtp.Password": "Heslo",
"DisplayName:Abp.Mailing.Smtp.Domain": "Doména",
"DisplayName:Abp.Mailing.Smtp.EnableSsl": "Povoliť SSL",
"DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Použiť predovlené prihlasovacie údaje",
"Description:Abp.Mailing.DefaultFromAddress": "Predvolené adresa Od",
"Description:Abp.Mailing.DefaultFromDisplayName": "Predvolené meno Od",
"Description:Abp.Mailing.Smtp.Host": "Názov alebo IP adresa host servera používaného pre SMTP transakcie.",
"Description:Abp.Mailing.Smtp.Port": "Port používaný pre SMTP transakcie.",
"Description:Abp.Mailing.Smtp.UserName": "Meno používateľa spojené s prihlasovacími údajmi.",
"Description:Abp.Mailing.Smtp.Password": "Heslo pre používateľské meno spojené s prihlasovacími údajmi.",
"Description:Abp.Mailing.Smtp.Domain": "Názov domény alebo počítača, ktorý overuje prihlasovacie údaje.",
"Description:Abp.Mailing.Smtp.EnableSsl": "Či SMTP klient používa na šifrovanie spojenia Secure Sockets Layer (SSL).",
"Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Či sa spolu s požiadavkami posielajú aj predvolené prihlasovacie údaje.",
"TextTemplate:StandardEmailTemplates.Layout": "Predvolená šablóna rozloženia emailu",
"TextTemplate:StandardEmailTemplates.Message": "Jednoduchá šablóna správy pre emaily"
}
}

25
framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/sk.json

@ -0,0 +1,25 @@
{
"culture": "sk",
"texts": {
"InternalServerErrorMessage": "Počas vašej požiadavky došlo k internej chybe!",
"ValidationErrorMessage": "Vaša žiadosť nie je platná!",
"ValidationNarrativeErrorMessageTitle": "Počas overovania boli zistené tieto chyby.",
"DefaultErrorMessage": "Vyskytla sa chyba!",
"DefaultErrorMessageDetail": "Server neodoslal detail chyby.",
"DefaultErrorMessage401": "Nie ste autentifikovaný!",
"DefaultErrorMessage401Detail": "Ak chcete vykonať túto operáciu, mali by ste sa prihlásiť.",
"DefaultErrorMessage403": "Nie ste autorizovaný!",
"DefaultErrorMessage403Detail": "Nemáte povolenie vykonať túto operáciu!",
"DefaultErrorMessage404": "Zdroj nebol nájdený!",
"DefaultErrorMessage404Detail": "Požadovaný zdroj sa na serveri nenašiel!",
"EntityNotFoundErrorMessage": "Entita {0} s id = {1} neexistuje!",
"Error": "Error",
"UnhandledException": "Neošetrená výnimka!",
"401Message": "Neoprávnený",
"403Message": "Zakázané",
"404Message": "Stránka nebola nájdená",
"500Message": "Interná chyba servera",
"403MessageDetail": "Nie ste oprávnený vykonávať túto operáciu!",
"404MessageDetail": "Je nám ľúto, ale na tejto adrese sa nič nenachádza."
}
}

8
framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/sk.json

@ -0,0 +1,8 @@
{
"culture": "sk",
"texts": {
"Volo.Feature:010001": "Funkcia nie je povolená: {FeatureName}",
"Volo.Feature:010002": "Požadované funkcie nie sú povolené. Všetky tieto funkcie musia byť povolené: {FeatureNames}.",
"Volo.Feature:010003": "Požadované funkcie nie sú povolené. Aspoň jedna z týchto funkcií musí byť povolená: {FeatureNames}"
}
}

6
framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/sk.json

@ -0,0 +1,6 @@
{
"culture": "sk",
"texts": {
"Volo.GlobalFeature:010001": "Služba '{ServiceName}' musí povoliť funkciu '{GlobalFeatureName}'."
}
}

17
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Volo.Abp.Content;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
@ -57,7 +58,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
ICancellationTokenProvider cancellationTokenProvider,
ICorrelationIdProvider correlationIdProvider,
IOptions<AbpCorrelationIdOptions> correlationIdOptions,
ICurrentTenant currentTenant,
ICurrentTenant currentTenant,
IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider)
{
CancellationTokenProvider = cancellationTokenProvider;
@ -114,7 +115,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
* it before we finish doing our work with the stream */
return (T)(object)new RemoteStreamContent(await responseContent.ReadAsStreamAsync())
{
ContentType = responseContent.Headers.ContentType?.ToString()
ContentType = responseContent.Headers.ContentType?.ToString(),
FileName = responseContent.Headers?.ContentDisposition?.FileNameStar ??
RemoveQuotes(responseContent.Headers?.ContentDisposition?.FileName).ToString()
};
}
@ -293,6 +296,16 @@ namespace Volo.Abp.Http.Client.DynamicProxying
};
}
protected virtual StringSegment RemoveQuotes(StringSegment input)
{
if (!StringSegment.IsNullOrEmpty(input) && input.Length >= 2 && input[0] == '"' && input[input.Length - 1] == '"')
{
input = input.Subsegment(1, input.Length - 2);
}
return input;
}
protected virtual CancellationToken GetCancellationToken()
{
return CancellationTokenProvider.Token;

5
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs

@ -90,8 +90,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
if (!remoteStreamContent.ContentType.IsNullOrWhiteSpace())
{
streamContent.Headers.ContentType = new MediaTypeHeaderValue(remoteStreamContent.ContentType);
}
formData.Add(streamContent, parameter.Name, parameter.Name);
formData.Add(streamContent, parameter.Name, remoteStreamContent.FileName ?? parameter.Name);
}
else if (value is IEnumerable<IRemoteStreamContent> remoteStreamContents)
{
@ -107,7 +108,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
streamContent.Headers.ContentType = new MediaTypeHeaderValue(content.ContentType);
}
formData.Add(streamContent, parameter.Name, parameter.Name);
formData.Add(streamContent, parameter.Name, content.FileName ?? parameter.Name);
}
}
else

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save