Browse Source

Merge branch 'dev' into gterdem/organization_unit_enhancement

pull/4186/head
Galip Tolga Erdem 6 years ago
parent
commit
6549cd4fc4
  1. 17
      docs/en/Entity-Framework-Core-MySQL.md
  2. 67
      docs/en/Entity-Framework-Core-Oracle.md
  3. 1
      docs/en/Entity-Framework-Core-Other-DBMS.md
  4. 62
      docs/en/UI/Angular/Localization.md
  5. 4
      docs/en/docs-nav.json
  6. 31
      docs/zh-Hans/CLI.md
  7. 17
      docs/zh-Hans/Entity-Framework-Core-MySQL.md
  8. 73
      docs/zh-Hans/Entity-Framework-Core-Oracle.md
  9. 1
      docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md
  10. 2
      docs/zh-Hans/Getting-Started.md
  11. 62
      docs/zh-Hans/UI/Angular/Localization.md
  12. 4
      docs/zh-Hans/docs-nav.json
  13. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs
  14. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs
  15. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs
  16. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs
  17. 109
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  18. 40
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  19. 12
      framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs
  20. 113
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs
  21. 7
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs
  22. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderDeleteArgs.cs
  23. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderExistsArgs.cs
  24. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderGetArgs.cs
  25. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderSaveArgs.cs
  26. 45
      framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs
  27. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/IDomainService.cs
  28. 5
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs
  29. 10
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs
  30. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  31. 13
      framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj
  32. 25
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/AbpTimingModule.cs
  33. 18
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs
  34. 10
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/AbpTimingResource.cs
  35. 7
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/en.json
  36. 7
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/tr.json
  37. 7
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/zh-Hans.json
  38. 7
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/zh-Hant.json
  39. 36
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs
  40. 7
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingNames.cs
  41. 25
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs
  42. 16
      framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs
  43. 17
      framework/test/Volo.Abp.Core.Tests/System/ObjectExtension_Test.cs
  44. 3
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs
  45. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs
  46. 5
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContextModelBuilderExtensions.cs
  47. 81
      modules/blob-storing-database/Volo.Abp.BlobStoring.Database.sln
  48. 23
      modules/blob-storing-database/Volo.Abp.BlobStoring.Database.sln.DotSettings
  49. 3
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/FodyWeavers.xml
  50. 30
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/FodyWeavers.xsd
  51. 20
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.csproj
  52. 37
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainSharedModule.cs
  53. 7
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseErrorCodes.cs
  54. 15
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseBlobConsts.cs
  55. 7
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseContainerConsts.cs
  56. 10
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/BlobStoringDatabaseResource.cs
  57. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/cs.json
  58. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/en.json
  59. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pl-PL.json
  60. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pt-BR.json
  61. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/sl.json
  62. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/tr.json
  63. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/vi.json
  64. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hans.json
  65. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hant.json
  66. 3
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/FodyWeavers.xml
  67. 30
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/FodyWeavers.xsd
  68. 17
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.csproj
  69. 13
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDbProperties.cs
  70. 15
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs
  71. 44
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlob.cs
  72. 21
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainer.cs
  73. 12
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainerConfigurationExtensions.cs
  74. 120
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs
  75. 13
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobContainerRepository.cs
  76. 17
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs
  77. 3
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/FodyWeavers.xml
  78. 30
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/FodyWeavers.xsd
  79. 16
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.csproj
  80. 23
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreModule.cs
  81. 27
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContext.cs
  82. 47
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContextModelCreatingExtensions.cs
  83. 18
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringModelBuilderConfigurationOptions.cs
  84. 23
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs
  85. 53
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs
  86. 14
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/IBlobStoringDbContext.cs
  87. 3
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/FodyWeavers.xml
  88. 30
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/FodyWeavers.xsd
  89. 16
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.csproj
  90. 22
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoDbModule.cs
  91. 21
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContext.cs
  92. 31
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContextExtensions.cs
  93. 14
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoModelBuilderConfigurationOptions.cs
  94. 14
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/IBlobStoringMongoDbContext.cs
  95. 21
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobContainerRepository.cs
  96. 45
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs
  97. 10
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/BlobStoringDatabaseDomainTestBase.cs
  98. 13
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/BlobStoringDatabaseDomainTestModule.cs
  99. 13
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.csproj
  100. 7
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestBase.cs

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

@ -25,23 +25,6 @@ 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
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:
````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.
## Re-Generate the Migrations
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.

67
docs/en/Entity-Framework-Core-Oracle.md

@ -0,0 +1,67 @@
# Switch to EF Core Oracle Provider
This document explains how to switch to the **Oracle** database provider for **[the application startup template](Startup-Templates/Application.md)** which comes with SQL Server provider pre-configured.
> This document uses a paid library of [Devart](https://www.devart.com/dotconnect/oracle/) company, because it is the only library for Oracle that supports EF Core 3.x.
## Replace the Volo.Abp.EntityFrameworkCore.SqlServer Package
`.EntityFrameworkCore` project in the solution depends on the [Volo.Abp.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.SqlServer) NuGet package. Remove this package and add the same version of the [Volo.Abp.EntityFrameworkCore.Oracle.Devart](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.Oracle.Devart) package.
## Replace the Module Dependency
Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFrameworkCore` project, remove `typeof(AbpEntityFrameworkCoreSqlServerModule)` from the `DependsOn` attribute, add `typeof(AbpEntityFrameworkCoreOracleDevartModule)` (also replace `using Volo.Abp.EntityFrameworkCore.SqlServer;` with `using Volo.Abp.EntityFrameworkCore.Oracle.Devart;`).
## UseOracle()
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.
In the `CreateDbContext()` method of the *YourProjectName*MigrationsDbContextFactory.cs, replace the following code block
```
var builder = new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
```
with this one
```
var builder = (DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>)
new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>().UseOracle
(
configuration.GetConnectionString("Default")
);
```
> Depending on your solution structure, you may find more code files need to be changed.
## Change the Connection Strings
Oracle connection strings are different than SQL Server connection strings. So, check all `appsettings.json` files in your solution and replace the connection strings inside them. See the [connectionstrings.com]( https://www.connectionstrings.com/oracle/ ) for details of Oracle connection string options.
You typically will change the `appsettings.json` inside the `.DbMigrator` and `.Web` projects, but it depends on your solution structure.
A sample connection string for Oracle:
```
Data Source=localhost;User Id=myuser;Password=mypassword;
```
## Re-Generate the Migrations
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).
This will scaffold a new migration for Oracle.
Run the `.DbMigrator` project to create the database, apply the changes and seed the initial data.
## Run the Application
It is ready. Just run the application and enjoy coding.

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

@ -6,6 +6,7 @@ ABP framework provides **integration packages** for some common DBMSs to make th
* [MySQL](Entity-Framework-Core-MySQL.md)
* [PostgreSQL](Entity-Framework-Core-PostgreSQL.md)
* [Oracle](Entity-Framework-Core-Oracle.md)
* [SQLite](Entity-Framework-Core-SQLite.md)
However, you can configure your DBMS provider **without** these integration packages. While using the integration package is always recommended (it also makes standard for the depended version across different modules), you can do it manually if there is no integration package for your DBMS provider.

62
docs/en/UI/Angular/Localization.md

@ -130,6 +130,68 @@ this.store.selectSnapshot(
Localization resources are stored in the `localization` property of `ConfigState`.
## RTL Support
As of v2.9 ABP has RTL support. If you are generating a new project with v2.9 and above, everything is set, you do not need to do any changes. If you are migrating your project from an earlier version, please follow the 2 steps below:
#### Step 1. Create Chunks for Bootstrap LTR and RTL
Find [styles configuration in angular.json](https://angular.io/guide/workspace-config#style-script-config) and make sure the chunks in your project has `bootstrap-rtl.min` and `bootstrap-ltr.min` as shown below.
```json
{
"projects": {
"MyProjectName": {
"architect": {
"build": {
"options": {
"styles": [
{
"input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap-ltr.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"inject": true,
"bundleName": "fontawesome-all.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"inject": true,
"bundleName": "fontawesome-v4-shims.min"
},
"apps/dev-app/src/styles.scss"
],
}
}
}
}
}
}
#### Step 2. Clear Lazy Loaded Fontawesome in AppComponent
If you have created and injected chunks for Fontawesome as seen above, you no longer need the lazy loading in the `AppComponent` which was implemented before v2.9. Simply remove them. The `AppComponent` in the template of the new version looks like this:
```js
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<router-outlet></router-outlet>
`,
})
export class AppComponent {}
```
## See Also

4
docs/en/docs-nav.json

@ -440,6 +440,10 @@
"text": "To PostgreSQL",
"path": "Entity-Framework-Core-PostgreSQL.md"
},
{
"text": "To Oracle",
"path": "Entity-Framework-Core-Oracle.md"
},
{
"text": "To SQLite",
"path": "Entity-Framework-Core-SQLite.md"

31
docs/zh-Hans/CLI.md

@ -18,6 +18,37 @@ dotnet tool update -g Volo.Abp.Cli
## Commands
这里是所有可用的命令列表:
* **`help`**: 展示ABP CLI的用法帮助信息.
* **`new`**:生成基于ABP的[启动模板](Startup-Templates/Index.md).
* **`update`**:自动更新的ABP解决方案ABP相关的NuGet和NPM包.
* **`add-package`**: 添加ABP包到项目.
* **`add-module`**: 添加[应用模块](https://docs.abp.io/en/abp/latest/Modules/Index)到解决方案.
* **`generate-proxy`**: 生成客户端代理以使用服务器上的HTTP API端点.
* **`switch-to-preview`**: 切换解决方案所有ABP相关包为[夜间构建](Nightly-Builds.md)版本.
* **`switch-to-stable`**: 切换解决方案所有ABP相关包为最新的稳定版本.
* **`translate`**: 当源代码控制存储库中有多个JSON[本地化](Localization.md文件时,可简化翻译本地化文件的过程.
* **`login`**: 使用你在[abp.io](https://abp.io/)的用户名和密码在你的计算机上认证.
* **`logout`**: 在你的计算机注销认证.
### help
展示ABP CLI的基本用法:
用法:
````bash
abp help [command-name]
````
示例:
````bash
abp help # Shows a general help.
abp help new # Shows help about the "new" command.
````
### new
生成基于ABP[启动模板](Startup-Templates/Index.md)的新解决方案.

17
docs/zh-Hans/Entity-Framework-Core-MySQL.md

@ -25,23 +25,6 @@ MySQL连接字符串与SQL Server连接字符串不同. 所以检查你的解决
通常需要更改 `.DbMigrator``.Web` 项目里面的 `appsettings.json` ,但它取决于你的解决方案结构.
## 更改迁移DbContext
MySQL DBMS与SQL Server有一些细微的差异. 某些模块数据库映射配置(尤其是字段长度)会导致MySQL出现问题. 例如某些[IdentityServer模块](Modules/IdentityServer.md)表就存在这样的问题,它提供了一个选项可以根据你的DBMS配置字段.
启动模板包含*YourProjectName*MigrationsDbContext,它负责维护和迁移数据库架构. 此DbContext基本上调用依赖模块的扩展方法来配置其数据库表.
打开 *YourProjectName*MigrationsDbContext 更改 `builder.ConfigureIdentityServer();` 行,如下所示:
````csharp
builder.ConfigureIdentityServer(options =>
{
options.DatabaseProvider = EfCoreDatabaseProvider.MySql;
});
````
然后 `ConfigureIdentityServer()` 方法会将字段长度设置为不超过MySQL的限制. 如果在创建或执行数据库迁移时遇到任何问题请参考相关的模块文档.
## 重新生成迁移
启动模板使用[Entity Framework Core的Code First迁移](https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/). EF Core迁移取决于所选的DBMS提供程序. 因此更改DBMS提供程序会导致迁移失败.

73
docs/zh-Hans/Entity-Framework-Core-Oracle.md

@ -0,0 +1,73 @@
# 切换到EF Core Oracle提供程序
本文介绍如何将预配置为SqlServer提供程序的 **[应用程序启动模板](Startup-Templates/Application.md)** 切换到 **Oracle** 数据库提供程序
> 本文档使用[Devart](https://www.devart.com/dotconnect/oracle/)公司的付费库,因为它是oracle唯一支持EF Core 3.x的库
## 替换Volo.Abp.EntityFrameworkCore.SqlServer包
解决方案中的 `.EntityFrameworkCore` 项目依赖于 [Volo.Abp.EntityFrameworkCore.SqlServer](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.SqlServer) NuGet包. 删除这个包并且添加相同版本的 [Volo.Abp.EntityFrameworkCore.Oracle.Devart](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.Oracle.Devart) 包.
## 替换模块依赖项
`.EntityFrameworkCore` 项目中找到 **YourProjectName*EntityFrameworkCoreModule** 类, 删除 `DependsOn` attribute 上的`typeof(AbpEntityFrameworkCoreSqlServerModule)`, 添加 `typeof(AbpEntityFrameworkCoreOracleDevartModule)` (或者替换 `using Volo.Abp.EntityFrameworkCore.SqlServer;``using Volo.Abp.EntityFrameworkCore.Oracle.Devart;`).
## UseOracle()
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.
In the `CreateDbContext()` method of the *YourProjectName*MigrationsDbContextFactory.cs, replace the following code block
查找你的解决方案中 `UseSqlServer()`调用,替换为 `UseOracle()`. 检查下列文件:
* `.EntityFrameworkCore` 项目中的*YourProjectName*EntityFrameworkCoreModule.cs.
* `.EntityFrameworkCore` 项目中的*YourProjectName*MigrationsDbContextFactory.cs.
使用以下代码替换*YourProjectName*MigrationsDbContextFactory.cs中的 `CreateDbContext()` 方法:
```
var builder = new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"));
```
与这个
```
var builder = (DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>)
new DbContextOptionsBuilder<YourProjectNameMigrationsDbContext>().UseOracle
(
configuration.GetConnectionString("Default")
);
```
> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件.
## 更改连接字符串
Oracle连接字符串与SQL Server连接字符串不同. 所以检查你的解决方案中所有的 `appsettings.json` 文件,更改其中的连接字符串. 有关oracle连接字符串选项的详细内容请参见[connectionstrings.com](https://www.connectionstrings.com/oracle/).
通常需要更改 `.DbMigrator``.Web` 项目里面的 `appsettings.json` ,但它取决于你的解决方案结构.
Oracle连接字符串示例:
```
Data Source=localhost;User Id=myuser;Password=mypassword;
```
## 重新生成迁移
启动模板使用[Entity Framework Core的Code First迁移](https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/). EF Core迁移取决于所选的DBMS提供程序. 因此更改DBMS提供程序会导致迁移失败.
* 删除 `.EntityFrameworkCore.DbMigrations` 项目下的Migrations文件夹,并重新生成解决方案.
* 在包管理控制台中运行 `Add-Migration "Initial"`(在解决方案资源管理器选择 `.DbMigrator` (或 `.Web`) 做为启动项目并且选择 `.EntityFrameworkCore.DbMigrations` 做为默认项目).
这将创建一个配置所有数据库对象(表)的数据库迁移.
运行 `.DbMigrator` 项目创建数据库和初始种子数据.
## 运行应用程序
它已准备就绪, 只需要运行该应用程序与享受编码.

1
docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md

@ -6,6 +6,7 @@ ABP框架为一些常见的DMBS提供了简化配置的**集成包**,你可以
* [MySQL](Entity-Framework-Core-MySQL.md)
* [PostgreSQL](Entity-Framework-Core-PostgreSQL.md)
* [Oracle](Entity-Framework-Core-Oracle.md)
* [SQLite](Entity-Framework-Core-SQLite.md)
你也可以不使用集成包配置DBMS提供程序,虽然总是建议使用集成包(它也使不同模块之间的依赖版本成为标准版本),但是如果没有用于DBMS提供程序的集成包,也可以手动集成.

2
docs/zh-Hans/Getting-Started.md

@ -403,7 +403,7 @@ yarn start
在上面的管理界面中,可以通过使用[Expo Client](https://expo.io/tools#client)扫描二维码,使用Android模拟器,iOS模拟器或真机来启动应用程序.
> 请参阅[expo.io](https://docs.expo.io/versions/v36.0.0/workflow/ios-simulator/)上的[Android Studio模拟器](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/)和[iOS模拟器文档](https://docs.expo.io/versions/v36.0.0/workflow/android-studio-emulator/).
> 请参阅expo.io上的[Android Studio模拟器](https://docs.expo.io/workflow/android-simulator/)和[iOS模拟器文档](https://docs.expo.io/workflow/ios-simulator/).
![React Native login screen on iPhone 11](images/rn-login-iphone.png)

62
docs/zh-Hans/UI/Angular/Localization.md

@ -130,6 +130,68 @@ this.store.selectSnapshot(
本地化资源存储在 `ConfigState``localization` 属性中.
## RTL支持
从v2.9开始,ABP支持RTL. 如果使用v2.9及更高版本生成新项目,你无需进行任何更改. 如果要从早期版本迁移项目,请按照以下2个步骤操作:
#### 步骤 1. 为 Bootstrap LRT和RTL创建Chunks
在[angular.json中找到样式配置](https://angular.io/guide/workspace-config#style-script-config)确保项目中的chunks含有 `bootstrap-rtl.min``bootstrap-ltr.min`:
```json
{
"projects": {
"MyProjectName": {
"architect": {
"build": {
"options": {
"styles": [
{
"input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap-ltr.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
"inject": true,
"bundleName": "fontawesome-all.min"
},
{
"input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
"inject": true,
"bundleName": "fontawesome-v4-shims.min"
},
"apps/dev-app/src/styles.scss"
],
}
}
}
}
}
}
#### 步骤 2. 清除AppComponent中延迟加载的Fontawesome
如果你如上所述为Fontawesome创建并且注入了chunks,就不再需要v2.9版本之前的实现的 `AppComponent` 延迟加载. 删除它们即可,新版的 `AppComponent` 如下所示:
```js
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<router-outlet></router-outlet>
`,
})
export class AppComponent {}
```
## 另请参阅
* [ASP.NET Core中的本地化](../../Localization.md)

4
docs/zh-Hans/docs-nav.json

@ -430,6 +430,10 @@
"text": "到PostgreSQL",
"path": "Entity-Framework-Core-PostgreSQL.md"
},
{
"text": " Oracle",
"path": "Entity-Framework-Core-Oracle.md"
},
{
"text": "到SQLite",
"path": "Entity-Framework-Core-SQLite.md"

7
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs

@ -1,6 +1,7 @@
using System;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending;
using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
@ -21,6 +22,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
public CurrentTenantDto CurrentTenant { get; set; }
public TimingDto Timing { get; set; }
public ClockDto Clock { get; set; }
public ObjectExtensionsDto ObjectExtensions { get; set; }
}
}
}

7
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
public class ClockDto
{
public string Kind { get; set; }
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs

@ -0,0 +1,24 @@
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
public class TimingDto
{
public TimeZone TimeZone { get; set; }
}
public class TimeZone
{
public IanaTimeZone Iana { get; set; }
public WindowsTimeZone Windows { get; set; }
}
public class WindowsTimeZone
{
public string TimeZoneId { get; set; }
}
public class IanaTimeZone
{
public string TimeZoneName { get; set; }
}
}

13
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs

@ -9,6 +9,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
[DependsOn(typeof(JQueryScriptContributor))]
public class BootstrapDatepickerScriptContributor : BundleContributor
{
public static readonly Dictionary<string, string> CultureMap = new Dictionary<string, string>
{
{"zh-Hans", "zh-CN"}
};
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/libs/bootstrap-datepicker/bootstrap-datepicker.min.js");
@ -21,10 +26,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
? "en"
: CultureInfo.CurrentUICulture.Name;
if (TryAddCultureFile(context, MapCultureName(cultureName)))
{
return;
}
TryAddCultureFile(context, MapCultureName(cultureName));
}
protected virtual bool TryAddCultureFile(BundleConfigurationContext context, string cultureName)
@ -42,7 +44,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
protected virtual string MapCultureName(string cultureName)
{
return cultureName;
return CultureMap.GetOrDefault(cultureName) ??
cultureName;
}
}
}

109
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js

@ -1,6 +1,10 @@
(function ($) {
function enableFormFeatures($forms, validate) {
abp.dom = abp.dom || {};
abp.dom.initializers = abp.dom.initializers || {};
abp.dom.initializers.initializeForms = function ($forms, validate) {
if ($forms.length) {
$forms.each(function () {
var $form = $(this);
@ -30,9 +34,9 @@
}
});
}
}
};
function initializeScript($el) {
abp.dom.initializers.initializeScript = function ($el) {
$el.findWithSelf('[data-script-class]').each(function () {
var scriptClassName = $(this).attr('data-script-class');
if (!scriptClassName) {
@ -51,20 +55,86 @@
});
}
abp.dom.onNodeAdded(function (args) {
args.$el.findWithSelf('[data-toggle="tooltip"]').tooltip({
abp.dom.initializers.initializeToolTips = function ($tooltips) {
$tooltips.tooltip({
container: 'body'
});
}
args.$el.findWithSelf('[data-toggle="popover"]').popover({
abp.dom.initializers.initializePopovers = function ($popovers) {
$popovers.popover({
container: 'body'
});
}
args.$el.findWithSelf('.timeago').timeago();
abp.dom.initializers.initializeTimeAgos = function ($timeagos) {
$timeagos.timeago();
}
enableFormFeatures(args.$el.findWithSelf('form'), true);
abp.libs = abp.libs = abp.libs || {};
abp.libs.bootstrapDatepicker = {
languageMap: {
'zh-Hans': 'zh-CN'
},
mapLanguageName: function (name) {
return abp.libs.bootstrapDatepicker.languageMap[abp.localization.currentCulture.name] || name;
},
isLanguageMapped: function (name) {
return abp.libs.bootstrapDatepicker.languageMap[abp.localization.currentCulture.name] !== undefined;
},
getCurrentLanguageConfig: function () {
var mappedName = abp.libs.bootstrapDatepicker.mapLanguageName(abp.localization.currentCulture.name);
return $.fn.datepicker.dates[mappedName];
},
normalizeLanguageConfig: function () {
var languageConfig = abp.libs.bootstrapDatepicker.getCurrentLanguageConfig();
if (languageConfig) {
if (!languageConfig.format || abp.libs.bootstrapDatepicker.isLanguageMapped(abp.localization.currentCulture.name)) {
languageConfig.format = abp.localization.currentCulture.dateTimeFormat.shortDatePattern.toLowerCase();
}
}
},
getFormattedValue: function (isoFormattedValue) {
if (!isoFormattedValue) {
return isoFormattedValue;
}
return luxon
.DateTime
.fromISO(isoFormattedValue, {
locale: abp.localization.currentCulture.name
}).toLocaleString();
},
getOptions($input) { //$input may needed if developer wants to override this method
return {
todayBtn: "linked",
autoclose: true,
language: abp.libs.bootstrapDatepicker.mapLanguageName(abp.localization.currentCulture.cultureName)
};
}
};
abp.dom.initializers.initializeDatepickers = function ($rootElement) {
$rootElement
.findWithSelf('input.datepicker,input[type=date]')
.each(function () {
var $input = $(this);
$input
.attr('type', 'text')
.val(abp.libs.bootstrapDatepicker.getFormattedValue($input.val()))
.datepicker(abp.libs.bootstrapDatepicker.getOptions($input))
.on('hide', function (e) {
e.stopPropagation();
});
});
}
initializeScript(args.$el);
abp.dom.onNodeAdded(function (args) {
abp.dom.initializers.initializeToolTips(args.$el.findWithSelf('[data-toggle="tooltip"]'));
abp.dom.initializers.initializePopovers(args.$el.findWithSelf('[data-toggle="popover"]'));
abp.dom.initializers.initializeTimeAgos(args.$el.findWithSelf('.timeago'));
abp.dom.initializers.initializeDatepickers(args.$el);
abp.dom.initializers.initializeForms(args.$el.findWithSelf('form'), true);
abp.dom.initializers.initializeScript(args.$el);
});
abp.dom.onNodeRemoved(function (args) {
@ -73,19 +143,16 @@
});
});
$(function () {
enableFormFeatures($('form'));
$('[data-toggle="tooltip"]').tooltip({
container: 'body'
});
$('[data-toggle="popover"]').popover({
container: 'body'
});
$('.timeago').timeago();
abp.event.on('abp.configurationInitialized', function () {
abp.libs.bootstrapDatepicker.normalizeLanguageConfig();
});
$(function () {
abp.dom.initializers.initializeToolTips($('[data-toggle="tooltip"]'));
abp.dom.initializers.initializePopovers($('[data-toggle="popover"]'));
abp.dom.initializers.initializeTimeAgos($('.timeago'));
abp.dom.initializers.initializeDatepickers($(document));
abp.dom.initializers.initializeForms($('form'));
$('[data-auto-focus="true"]').first().findWithSelf('input,select').focus();
});

40
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -15,6 +15,7 @@ using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using Volo.Abp.Timing;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
@ -31,6 +32,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly ILanguageProvider _languageProvider;
private readonly ITimezoneProvider _timezoneProvider;
private readonly AbpClockOptions _abpClockOptions;
private readonly ICachedObjectExtensionsDtoService _cachedObjectExtensionsDtoService;
public AbpApplicationConfigurationAppService(
@ -44,6 +47,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
ISettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider,
ITimezoneProvider timezoneProvider,
IOptions<AbpClockOptions> abpClockOptions,
ICachedObjectExtensionsDtoService cachedObjectExtensionsDtoService)
{
_serviceProvider = serviceProvider;
@ -54,6 +59,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
_settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager;
_languageProvider = languageProvider;
_timezoneProvider = timezoneProvider;
_abpClockOptions = abpClockOptions.Value;
_cachedObjectExtensionsDtoService = cachedObjectExtensionsDtoService;
_localizationOptions = localizationOptions.Value;
_multiTenancyOptions = multiTenancyOptions.Value;
@ -74,6 +81,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
Setting = await GetSettingConfigAsync(),
MultiTenancy = GetMultiTenancy(),
CurrentTenant = GetCurrentTenant(),
Timing = await GetTimingConfigAsync(),
Clock = GetClockConfig(),
ObjectExtensions = _cachedObjectExtensionsDtoService.Get()
};
@ -226,5 +235,36 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return result;
}
protected virtual async Task<TimingDto> GetTimingConfigAsync()
{
var result = new TimingDto();
var windowsTimeZoneId = await _settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone);
if (!windowsTimeZoneId.IsNullOrWhiteSpace())
{
result.TimeZone = new TimeZone
{
Windows = new WindowsTimeZone
{
TimeZoneId = windowsTimeZoneId
},
Iana = new IanaTimeZone()
{
TimeZoneName = _timezoneProvider.WindowsToIana(windowsTimeZoneId)
}
};
}
return result;
}
protected virtual ClockDto GetClockConfig()
{
return new ClockDto
{
Kind = Enum.GetName(typeof(DateTimeKind), _abpClockOptions.Kind)
};
}
}
}

12
framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs

@ -1,22 +1,30 @@
using System.IO;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BlobStoring.FileSystem
{
public class DefaultBlobFilePathCalculator : IBlobFilePathCalculator, ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }
public DefaultBlobFilePathCalculator(ICurrentTenant currentTenant)
{
CurrentTenant = currentTenant;
}
public virtual string Calculate(BlobProviderArgs args)
{
var fileSystemConfiguration = args.Configuration.GetFileSystemConfiguration();
var blobPath = fileSystemConfiguration.BasePath;
if (args.TenantId == null)
if (CurrentTenant.Id == null)
{
blobPath = Path.Combine(blobPath, "host");
}
else
{
blobPath = Path.Combine(blobPath, "tenants", args.TenantId.Value.ToString("D"));
blobPath = Path.Combine(blobPath, "tenants", CurrentTenant.Id.Value.ToString("D"));
}
if (fileSystemConfiguration.AppendContainerNameToBasePath)

113
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs

@ -79,9 +79,9 @@ namespace Volo.Abp.BlobStoring
protected BlobContainerConfiguration Configuration { get; }
protected IBlobProvider Provider { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public BlobContainer(
@ -98,100 +98,101 @@ namespace Volo.Abp.BlobStoring
CancellationTokenProvider = cancellationTokenProvider;
}
public virtual Task SaveAsync(
public virtual async Task SaveAsync(
string name,
Stream stream,
bool overrideExisting = false,
CancellationToken cancellationToken = default)
{
return Provider.SaveAsync(
new BlobProviderSaveArgs(
ContainerName,
Configuration,
name,
stream,
overrideExisting,
GetTenantIdOrNull(),
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
await Provider.SaveAsync(
new BlobProviderSaveArgs(
ContainerName,
Configuration,
name,
stream,
overrideExisting,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
}
}
public virtual Task<bool> DeleteAsync(
public virtual async Task<bool> DeleteAsync(
string name,
CancellationToken cancellationToken = default)
{
return Provider.DeleteAsync(
new BlobProviderDeleteArgs(
ContainerName,
Configuration,
name,
GetTenantIdOrNull(),
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
return await Provider.DeleteAsync(
new BlobProviderDeleteArgs(
ContainerName,
Configuration,
name,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
}
}
public virtual Task<bool> ExistsAsync(
public virtual async Task<bool> ExistsAsync(
string name,
CancellationToken cancellationToken = default)
{
return Provider.ExistsAsync(
new BlobProviderExistsArgs(
ContainerName,
Configuration,
name,
GetTenantIdOrNull(),
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
return await Provider.ExistsAsync(
new BlobProviderExistsArgs(
ContainerName,
Configuration,
name,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
}
}
public virtual async Task<Stream> GetAsync(
string name,
CancellationToken cancellationToken = default)
{
var stream = await Provider.GetOrNullAsync(
new BlobProviderGetArgs(
ContainerName,
Configuration,
name,
GetTenantIdOrNull(),
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
var stream = await GetOrNullAsync(name, cancellationToken);
if (stream == null)
{
//TODO: Consider to throw some type of "not found" exception and handle on the HTTP status side
throw new AbpException($"Could not found the requested BLOB '{name}' in the container '{ContainerName}'!");
throw new AbpException(
$"Could not found the requested BLOB '{name}' in the container '{ContainerName}'!");
}
return stream;
}
public virtual Task<Stream> GetOrNullAsync(
public virtual async Task<Stream> GetOrNullAsync(
string name,
CancellationToken cancellationToken = default)
{
return Provider.GetOrNullAsync(
new BlobProviderGetArgs(
ContainerName,
Configuration,
name,
GetTenantIdOrNull(),
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
using (CurrentTenant.Change(GetTenantIdOrNull()))
{
return await Provider.GetOrNullAsync(
new BlobProviderGetArgs(
ContainerName,
Configuration,
name,
CancellationTokenProvider.FallbackToProvider(cancellationToken)
)
);
}
}
protected virtual Guid? GetTenantIdOrNull()
{
if (!Configuration.IsMultiTenant)
{
return null;
}
return CurrentTenant.Id;
}
}

7
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs

@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
using JetBrains.Annotations;
namespace Volo.Abp.BlobStoring
@ -16,20 +15,16 @@ namespace Volo.Abp.BlobStoring
public string BlobName { get; }
public CancellationToken CancellationToken { get; }
public Guid? TenantId { get; }
protected BlobProviderArgs(
[NotNull] string containerName,
[NotNull] BlobContainerConfiguration configuration,
[NotNull] string blobName,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
{
ContainerName = Check.NotNullOrWhiteSpace(containerName, nameof(containerName));
Configuration = Check.NotNull(configuration, nameof(configuration));
BlobName = Check.NotNullOrWhiteSpace(blobName, nameof(blobName));
TenantId = tenantId;
CancellationToken = cancellationToken;
}
}

5
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderDeleteArgs.cs

@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
using JetBrains.Annotations;
namespace Volo.Abp.BlobStoring
@ -10,13 +9,11 @@ namespace Volo.Abp.BlobStoring
[NotNull] string containerName,
[NotNull] BlobContainerConfiguration configuration,
[NotNull] string blobName,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
: base(
containerName,
configuration,
blobName,
tenantId,
cancellationToken)
{
}

5
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderExistsArgs.cs

@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
using JetBrains.Annotations;
namespace Volo.Abp.BlobStoring
@ -10,13 +9,11 @@ namespace Volo.Abp.BlobStoring
[NotNull] string containerName,
[NotNull] BlobContainerConfiguration configuration,
[NotNull] string blobName,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
: base(
containerName,
configuration,
blobName,
tenantId,
cancellationToken)
{
}

5
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderGetArgs.cs

@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
using JetBrains.Annotations;
namespace Volo.Abp.BlobStoring
@ -10,13 +9,11 @@ namespace Volo.Abp.BlobStoring
[NotNull] string containerName,
[NotNull] BlobContainerConfiguration configuration,
[NotNull] string blobName,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
: base(
containerName,
configuration,
blobName,
tenantId,
cancellationToken)
{
}

5
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderSaveArgs.cs

@ -1,5 +1,4 @@
using System;
using System.IO;
using System.IO;
using System.Threading;
using JetBrains.Annotations;
@ -18,13 +17,11 @@ namespace Volo.Abp.BlobStoring
[NotNull] string blobName,
[NotNull] Stream blobStream,
bool overrideExisting = false,
[CanBeNull] Guid? tenantId = null,
CancellationToken cancellationToken = default)
: base(
containerName,
configuration,
blobName,
tenantId,
cancellationToken)
{
BlobStream = Check.NotNull(blobStream, nameof(blobStream));

45
framework/src/Volo.Abp.Core/System/AbpObjectExtensions.cs

@ -42,5 +42,50 @@ namespace System
{
return list.Contains(item);
}
/// <summary>
/// Can be used to conditionally perform a function
/// on an object and return the modified or the original object.
/// It is useful for chained calls.
/// </summary>
/// <param name="obj">An object</param>
/// <param name="condition">A condition</param>
/// <param name="func">A function that is executed only if the condition is <code>true</code></param>
/// <typeparam name="T">Type of the object</typeparam>
/// <returns>
/// Returns the modified object (by the <paramref name="func"/> if the <paramref name="condition"/> is <code>true</code>)
/// or the original object if the <paramref name="condition"/> is <code>false</code>
/// </returns>
public static T If<T>(this T obj, bool condition, Func<T, T> func)
{
if (condition)
{
return func(obj);
}
return obj;
}
/// <summary>
/// Can be used to conditionally perform an action
/// on an object and return the original object.
/// It is useful for chained calls on the object.
/// </summary>
/// <param name="obj">An object</param>
/// <param name="condition">A condition</param>
/// <param name="action">An action that is executed only if the condition is <code>true</code></param>
/// <typeparam name="T">Type of the object</typeparam>
/// <returns>
/// Returns the original object.
/// </returns>
public static T If<T>(this T obj, bool condition, Action<T> action)
{
if (condition)
{
action(obj);
}
return obj;
}
}
}

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/IDomainService.cs

@ -3,7 +3,7 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Domain.Services
{
/// <summary>
/// This interface must be implemented by all domain services to identify them by convention.
/// This interface can be implemented by all domain services to identify them by convention.
/// </summary>
public interface IDomainService : ITransientDependency
{

5
framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs

@ -10,9 +10,10 @@ namespace Volo.Abp.EntityFrameworkCore
{
public static DbContextOptionsBuilder UseOracle(
[NotNull] this AbpDbContextConfigurationContext context,
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null,
bool useExistingConnectionIfAvailable = false)
{
if (context.ExistingConnection != null)
if (useExistingConnectionIfAvailable && context.ExistingConnection != null)
{
return context.DbContextOptions.UseOracle(context.ExistingConnection, oracleOptionsAction);
}

10
framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextOptionsOracleDevartExtensions.cs

@ -8,22 +8,24 @@ namespace Volo.Abp.EntityFrameworkCore
{
public static void UseOracle(
[NotNull] this AbpDbContextOptions options,
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null,
bool useExistingConnectionIfAvailable = false)
{
options.Configure(context =>
{
context.UseOracle(oracleOptionsAction);
context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable);
});
}
public static void UseOracle<TDbContext>(
[NotNull] this AbpDbContextOptions options,
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
[CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null,
bool useExistingConnectionIfAvailable = false)
where TDbContext : AbpDbContext<TDbContext>
{
options.Configure<TDbContext>(context =>
{
context.UseOracle(oracleOptionsAction);
context.UseOracle(oracleOptionsAction, useExistingConnectionIfAvailable);
});
}
}

2
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -129,7 +129,7 @@ namespace Volo.Abp.EntityFrameworkCore
return EfCoreDatabaseProvider.PostgreSql;
case "Pomelo.EntityFrameworkCore.MySql":
return EfCoreDatabaseProvider.MySql;
case "Devart.Data.Oracle.EFCore":
case "Devart.Data.Oracle.Entity.EFCore":
return EfCoreDatabaseProvider.Oracle;
case "Microsoft.EntityFrameworkCore.Sqlite":
return EfCoreDatabaseProvider.Sqlite;

13
framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj

@ -14,8 +14,19 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Timing\Localization\**\*.json" />
<Content Remove="Volo\Abp\Timing\Localization\**\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="TimeZoneConverter" Version="3.2.0" />
</ItemGroup>
</Project>

25
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/AbpTimingModule.cs

@ -1,9 +1,32 @@
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using Volo.Abp.Localization.Resources.AbpLocalization;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.Timing.Localization.Resources.AbpTiming;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Timing
{
[DependsOn(
typeof(AbpVirtualFileSystemModule),
typeof(AbpSettingsModule)
)]
public class AbpTimingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpTimingModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options
.Resources
.Add<AbpTimingResource>("en")
.AddVirtualJson("/Volo/Abp/Timing/Localization");
});
}
}
}

18
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/ITimezoneProvider.cs

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Timing
{
public interface ITimezoneProvider
{
List<NameValue> GetWindowsTimezones();
List<NameValue> GetIanaTimezones();
string WindowsToIana(string windowsTimeZoneId);
string IanaToWindows(string ianaTimeZoneName);
TimeZoneInfo GetTimeZoneInfo(string windowsOrIanaTimeZoneId);
}
}

10
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/AbpTimingResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.Timing.Localization.Resources.AbpTiming
{
[LocalizationResourceName("AbpTiming")]
public class AbpTimingResource
{
}
}

7
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/en.json

@ -0,0 +1,7 @@
{
"culture": "en",
"texts": {
"DisplayName:Abp.Timing.Timezone": "Timezone",
"Description:Abp.Timing.Timezone": "Application time zone"
}
}

7
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/tr.json

@ -0,0 +1,7 @@
{
"culture": "tr",
"texts": {
"DisplayName:Abp.Timing.Timezone": "saat dilimi",
"Description:Abp.Timing.Timezone": "Uygulama saat dilimi"
}
}

7
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"DisplayName:Abp.Timing.Timezone": "时区",
"Description:Abp.Timing.Timezone": "应用程序的时区"
}
}

7
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/zh-Hant.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hant",
"texts": {
"DisplayName:Abp.Timing.Timezone": "時區",
"Description:Abp.Timing.Timezone": "應用程序的時區"
}
}

36
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TimeZoneConverter;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Timing
{
public class TZConvertTimezoneProvider : ITimezoneProvider, ITransientDependency
{
public virtual List<NameValue> GetWindowsTimezones()
{
return TZConvert.KnownIanaTimeZoneNames.OrderBy(x => x).Select(x => new NameValue(x, x)).ToList();
}
public virtual List<NameValue> GetIanaTimezones()
{
return TZConvert.KnownIanaTimeZoneNames.OrderBy(x => x).Select(x => new NameValue(x, x)).ToList();
}
public virtual string WindowsToIana(string windowsTimeZoneId)
{
return TZConvert.WindowsToIana(windowsTimeZoneId);
}
public virtual string IanaToWindows(string ianaTimeZoneName)
{
return TZConvert.IanaToWindows(ianaTimeZoneName);
}
public virtual TimeZoneInfo GetTimeZoneInfo(string windowsOrIanaTimeZoneId)
{
return TZConvert.GetTimeZoneInfo(windowsOrIanaTimeZoneId);
}
}
}

7
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingNames.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.Timing
{
public static class TimingSettingNames
{
public const string TimeZone = "Abp.Timing.TimeZone";
}
}

25
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs

@ -0,0 +1,25 @@
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Timing.Localization.Resources.AbpTiming;
namespace Volo.Abp.Timing
{
public class TimingSettingProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(
new SettingDefinition(TimingSettingNames.TimeZone,
"UTC",
L("DisplayName:Abp.Timing.Timezone"),
L("Description:Abp.Timing.Timezone"),
isVisibleToClients: true)
);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<AbpTimingResource>(name);
}
}
}

16
framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs

@ -1,6 +1,7 @@
using System;
using System.IO;
using Shouldly;
using Volo.Abp.MultiTenancy;
using Xunit;
namespace Volo.Abp.BlobStoring.FileSystem
@ -8,10 +9,12 @@ namespace Volo.Abp.BlobStoring.FileSystem
public class BlogFilePathCalculator_Tests : AbpBlobStoringFileSystemTestBase
{
private readonly IBlobFilePathCalculator _calculator;
private readonly ICurrentTenant _currentTenant;
public BlogFilePathCalculator_Tests()
{
_calculator = GetRequiredService<IBlobFilePathCalculator>();
_currentTenant = GetRequiredService<ICurrentTenant>();
}
[Fact]
@ -30,9 +33,12 @@ namespace Volo.Abp.BlobStoring.FileSystem
var separator = Path.DirectorySeparatorChar;
var tenantId = Guid.NewGuid();
_calculator.Calculate(
GetArgs($"C:{separator}my-files", "my-container", "my-blob", tenantId: tenantId)
).ShouldBe($"C:{separator}my-files{separator}tenants{separator}{tenantId:D}{separator}my-container{separator}my-blob");
using (_currentTenant.Change(tenantId))
{
_calculator.Calculate(
GetArgs($"C:{separator}my-files", "my-container", "my-blob")
).ShouldBe($"C:{separator}my-files{separator}tenants{separator}{tenantId:D}{separator}my-container{separator}my-blob");
}
}
[Fact]
@ -49,7 +55,6 @@ namespace Volo.Abp.BlobStoring.FileSystem
string basePath,
string containerName,
string blobName,
Guid? tenantId = null,
bool? appendContainerNameToBasePath = null)
{
return new BlobProviderGetArgs(
@ -63,8 +68,7 @@ namespace Volo.Abp.BlobStoring.FileSystem
fs.AppendContainerNameToBasePath = appendContainerNameToBasePath.Value;
}
}),
blobName,
tenantId
blobName
);
}
}

17
framework/test/Volo.Abp.Core.Tests/System/ObjectExtension_Test.cs

@ -52,5 +52,22 @@ namespace System
str = null;
str.IsIn("a", "b", "c").ShouldBe(false);
}
[Fact]
public void If_Tests()
{
var value = 0;
value = value.If(true, v => v + 1);
value.ShouldBe(1);
value = value.If(false, v => v + 1);
value.ShouldBe(1);
value = value
.If(true, v => v + 3)
.If(false, v => v + 5);
value.ShouldBe(4);
}
}
}

3
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs

@ -16,6 +16,9 @@
public const int MaxExceptionsLength = 4000;
//TODO: Replace with MaxExceptionsLength in v3.0
public static int MaxExceptionsLengthValue { get; set; } = MaxExceptionsLength;
public const int MaxCommentsLength = 256;
public const int MaxUrlLength = 256;

2
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs

@ -99,7 +99,7 @@ namespace Volo.Abp.AuditLogging
Exceptions = auditInfo
.Exceptions?
.JoinAsString(Environment.NewLine)
.Truncate(AuditLogConsts.MaxExceptionsLength);
.Truncate(AuditLogConsts.MaxExceptionsLengthValue);
Comments = auditInfo
.Comments?

5
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingDbContextModelBuilderExtensions.cs

@ -36,7 +36,10 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
b.Property(x => x.HttpMethod).HasMaxLength(AuditLogConsts.MaxHttpMethodLength).HasColumnName(nameof(AuditLog.HttpMethod));
b.Property(x => x.Url).HasMaxLength(AuditLogConsts.MaxUrlLength).HasColumnName(nameof(AuditLog.Url));
b.Property(x => x.HttpStatusCode).HasColumnName(nameof(AuditLog.HttpStatusCode));
b.Property(x => x.Exceptions).HasMaxLength(AuditLogConsts.MaxExceptionsLength).HasColumnName(nameof(AuditLog.Exceptions));
if (builder.IsUsingOracle()) { AuditLogConsts.MaxExceptionsLengthValue = 2000; }
b.Property(x => x.Exceptions).HasMaxLength(AuditLogConsts.MaxExceptionsLengthValue).HasColumnName(nameof(AuditLog.Exceptions));
b.Property(x => x.Comments).HasMaxLength(AuditLogConsts.MaxCommentsLength).HasColumnName(nameof(AuditLog.Comments));
b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLog.ExecutionDuration));
b.Property(x => x.ImpersonatorTenantId).HasColumnName(nameof(AuditLog.ImpersonatorTenantId));

81
modules/blob-storing-database/Volo.Abp.BlobStoring.Database.sln

@ -0,0 +1,81 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29001.49
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.Domain.Shared", "src\Volo.Abp.BlobStoring.Database.Domain.Shared\Volo.Abp.BlobStoring.Database.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.Domain", "src\Volo.Abp.BlobStoring.Database.Domain\Volo.Abp.BlobStoring.Database.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.EntityFrameworkCore", "src\Volo.Abp.BlobStoring.Database.EntityFrameworkCore\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.MongoDB", "src\Volo.Abp.BlobStoring.Database.MongoDB\Volo.Abp.BlobStoring.Database.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.TestBase", "test\Volo.Abp.BlobStoring.Database.TestBase\Volo.Abp.BlobStoring.Database.TestBase.csproj", "{C5BB573D-3030-4BCB-88B7-F6A85C32766C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests", "test\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj", "{527F645C-C1FC-406E-8479-81386C8ECF13}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.MongoDB.Tests", "test\Volo.Abp.BlobStoring.Database.MongoDB.Tests\Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj", "{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlobStoring.Database.Domain.Tests", "test\Volo.Abp.BlobStoring.Database.Domain.Tests\Volo.Abp.BlobStoring.Database.Domain.Tests.csproj", "{E60895E5-79C4-447D-88B7-85CB5BA336A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.Build.0 = Release|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.Build.0 = Release|Any CPU
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.Build.0 = Release|Any CPU
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.Build.0 = Release|Any CPU
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D64C1577-4929-4B60-939E-96DE1534891A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
{F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
{0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
{F1C58097-4C08-4D88-8976-6B3389391481} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
{C5BB573D-3030-4BCB-88B7-F6A85C32766C} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
{527F645C-C1FC-406E-8479-81386C8ECF13} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
{E60895E5-79C4-447D-88B7-85CB5BA336A4} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD}
EndGlobalSection
EndGlobal

23
modules/blob-storing-database/Volo.Abp.BlobStoring.Database.sln.DotSettings

@ -0,0 +1,23 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceDoWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceFixedStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForeachStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceIfStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceLockStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceUsingStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_REDUNDANT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String>
</wpf:ResourceDictionary>

3
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

20
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\BlobStoring\Database\Localization\*.json" />
<Content Remove="Volo\Abp\BlobStoring\Database\Localization\*.json" />
</ItemGroup>
</Project>

37
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainSharedModule.cs

@ -0,0 +1,37 @@
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using Volo.Abp.BlobStoring.Database.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation;
using Volo.Abp.Validation.Localization;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.BlobStoring.Database
{
[DependsOn(
typeof(AbpValidationModule)
)]
public class BlobStoringDatabaseDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BlobStoringDatabaseDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<BlobStoringDatabaseResource>("en")
.AddBaseTypes(typeof(AbpValidationResource))
.AddVirtualJson("/Volo/Abp/BlobStoring/Database/Localization");
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("BlobStoringDatabase", typeof(BlobStoringDatabaseResource));
});
}
}
}

7
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseErrorCodes.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.BlobStoring.Database
{
public static class BlobStoringDatabaseErrorCodes
{
//Add your business exception error codes here...
}
}

15
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseBlobConsts.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.BlobStoring.Database
{
public static class DatabaseBlobConsts
{
/// <summary>
/// Default value: 256.
/// </summary>
public static int MaxNameLength { get; set; } = 256;
/// <summary>
/// Default value: <see cref="int.MaxValue"/> (2GB).
/// </summary>
public static int MaxContentLength { get; set; } = int.MaxValue;
}
}

7
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseContainerConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.BlobStoring.Database
{
public static class DatabaseContainerConsts
{
public const int MaxNameLength = 128;
}
}

10
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/BlobStoringDatabaseResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.BlobStoring.Database.Localization
{
[LocalizationResourceName("BlobStoringDatabase")]
public class BlobStoringDatabaseResource
{
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/cs.json

@ -0,0 +1,6 @@
{
"culture": "cs",
"texts": {
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"ManageYourProfile": "Manage your profile"
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pl-PL.json

@ -0,0 +1,6 @@
{
"culture": "pl-PL",
"texts": {
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pt-BR.json

@ -0,0 +1,6 @@
{
"culture": "pt-BR",
"texts": {
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/sl.json

@ -0,0 +1,6 @@
{
"culture": "sl",
"texts": {
"ManageYourProfile": "Upravljajte svojim profilom"
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/tr.json

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"ManageYourProfile": "Profil yönetimi"
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/vi.json

@ -0,0 +1,6 @@
{
"culture": "vi",
"texts": {
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hans.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"ManageYourProfile": "管理个人资料"
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hant.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hant",
"texts": {
"ManageYourProfile": "管理個人資料"
}
}

3
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

17
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.csproj

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.BlobStoring\Volo.Abp.BlobStoring.csproj" />
<ProjectReference Include="..\Volo.Abp.BlobStoring.Database.Domain.Shared\Volo.Abp.BlobStoring.Database.Domain.Shared.csproj" />
</ItemGroup>
</Project>

13
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDbProperties.cs

@ -0,0 +1,13 @@
using Volo.Abp.Data;
namespace Volo.Abp.BlobStoring.Database
{
public static class BlobStoringDatabaseDbProperties
{
public static string DbTablePrefix { get; set; } = AbpCommonDbProperties.DbTablePrefix;
public static string DbSchema { get; set; } = AbpCommonDbProperties.DbSchema;
public const string ConnectionStringName = "AbpBlobStoring";
}
}

15
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainModule.cs

@ -0,0 +1,15 @@
using Volo.Abp.Domain;
using Volo.Abp.Modularity;
namespace Volo.Abp.BlobStoring.Database
{
[DependsOn(
typeof(AbpDddDomainModule),
typeof(AbpBlobStoringModule),
typeof(BlobStoringDatabaseDomainSharedModule)
)]
public class BlobStoringDatabaseDomainModule : AbpModule
{
}
}

44
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlob.cs

@ -0,0 +1,44 @@
using JetBrains.Annotations;
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BlobStoring.Database
{
public class DatabaseBlob : AggregateRoot<Guid>, IMultiTenant
{
public virtual Guid ContainerId { get; protected set; }
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public virtual byte[] Content { get; protected set; }
public DatabaseBlob(Guid id, Guid containerId, [NotNull] string name, [NotNull] byte[] content, Guid? tenantId = null)
: base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), DatabaseBlobConsts.MaxNameLength);
ContainerId = containerId;
Content = CheckContentLength(content);
TenantId = tenantId;
}
public virtual void SetContent(byte[] content)
{
Content = CheckContentLength(content);
}
protected virtual byte[] CheckContentLength(byte[] content)
{
Check.NotNull(content, nameof(content));
if (content.Length >= DatabaseBlobConsts.MaxContentLength)
{
throw new AbpException($"Blob content size cannot be more than {DatabaseBlobConsts.MaxContentLength} Bytes.");
}
return content;
}
}
}

21
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainer.cs

@ -0,0 +1,21 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BlobStoring.Database
{
public class DatabaseBlobContainer : AggregateRoot<Guid>, IMultiTenant //TODO: Rename to BlobContainer
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public DatabaseBlobContainer(Guid id, [NotNull] string name, Guid? tenantId = null)
: base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), DatabaseContainerConsts.MaxNameLength);
TenantId = tenantId;
}
}
}

12
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainerConfigurationExtensions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.BlobStoring.Database
{
public static class DatabaseBlobContainerConfigurationExtensions
{
public static BlobContainerConfiguration UseDatabase(
this BlobContainerConfiguration containerConfiguration)
{
containerConfiguration.ProviderType = typeof(DatabaseBlobProvider);
return containerConfiguration;
}
}
}

120
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs

@ -0,0 +1,120 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
namespace Volo.Abp.BlobStoring.Database
{
public class DatabaseBlobProvider : BlobProviderBase, ITransientDependency
{
protected IDatabaseBlobRepository DatabaseBlobRepository { get; }
protected IDatabaseBlobContainerRepository DatabaseBlobContainerRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public DatabaseBlobProvider(
IDatabaseBlobRepository databaseBlobRepository,
IDatabaseBlobContainerRepository databaseBlobContainerRepository,
IGuidGenerator guidGenerator)
{
DatabaseBlobRepository = databaseBlobRepository;
DatabaseBlobContainerRepository = databaseBlobContainerRepository;
GuidGenerator = guidGenerator;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
{
var container = await GetOrCreateContainerAsync(args.ContainerName, args.CancellationToken);
var blob = await DatabaseBlobRepository.FindAsync(container.Id, args.BlobName,
args.CancellationToken);
var content = await args.BlobStream.GetAllBytesAsync(args.CancellationToken);
if (blob != null)
{
if (!args.OverrideExisting)
{
throw new BlobAlreadyExistsException(
$"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
}
blob.SetContent(content);
await DatabaseBlobRepository.UpdateAsync(blob);
}
else
{
blob = new DatabaseBlob(GuidGenerator.Create(), container.Id, args.BlobName, content);
await DatabaseBlobRepository.InsertAsync(blob);
}
}
public override async Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return false;
}
return await DatabaseBlobRepository.DeleteAsync(container.Id, args.BlobName,
args.CancellationToken);
}
public override async Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return false;
}
return await DatabaseBlobRepository.ExistsAsync(container.Id, args.BlobName,
args.CancellationToken);
}
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return null;
}
var blob = await DatabaseBlobRepository.FindAsync(container.Id, args.BlobName,
args.CancellationToken);
if (blob == null)
{
return null;
}
return new MemoryStream(blob.Content);
}
protected virtual async Task<DatabaseBlobContainer> GetOrCreateContainerAsync(
string name,
CancellationToken cancellationToken = default)
{
var container = await DatabaseBlobContainerRepository.FindAsync(name, cancellationToken);
if (container != null)
{
return container;
}
container = new DatabaseBlobContainer(GuidGenerator.Create(), name);
await DatabaseBlobContainerRepository.InsertAsync(container, cancellationToken: cancellationToken);
return container;
}
}
}

13
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobContainerRepository.cs

@ -0,0 +1,13 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.BlobStoring.Database
{
public interface IDatabaseBlobContainerRepository : IBasicRepository<DatabaseBlobContainer, Guid>
{
Task<DatabaseBlobContainer> FindAsync([NotNull] string name, CancellationToken cancellationToken = default);
}
}

17
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs

@ -0,0 +1,17 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.BlobStoring.Database
{
public interface IDatabaseBlobRepository : IBasicRepository<DatabaseBlob, Guid>
{
Task<DatabaseBlob> FindAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default);
}
}

3
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

16
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.EntityFrameworkCore\Volo.Abp.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\Volo.Abp.BlobStoring.Database.Domain\Volo.Abp.BlobStoring.Database.Domain.csproj" />
</ItemGroup>
</Project>

23
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreModule.cs

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
[DependsOn(
typeof(BlobStoringDatabaseDomainModule),
typeof(AbpEntityFrameworkCoreModule)
)]
public class BlobStoringDatabaseEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<BlobStoringDbContext>(options =>
{
options.AddRepository<DatabaseBlobContainer, EfCoreDatabaseBlobContainerRepository>();
options.AddRepository<DatabaseBlob, EfCoreDatabaseBlobRepository>();
});
}
}
}

27
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContext.cs

@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public class BlobStoringDbContext : AbpDbContext<BlobStoringDbContext>, IBlobStoringDbContext
{
public DbSet<DatabaseBlobContainer> BlobContainers { get; set; }
public DbSet<DatabaseBlob> Blobs { get; set; }
public BlobStoringDbContext(DbContextOptions<BlobStoringDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureBlobStoring();
}
}
}

47
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContextModelCreatingExtensions.cs

@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore;
using System;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public static class BlobStoringDbContextModelCreatingExtensions
{
public static void ConfigureBlobStoring(
this ModelBuilder builder,
Action<BlobStoringModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new BlobStoringModelBuilderConfigurationOptions(
BlobStoringDatabaseDbProperties.DbTablePrefix,
BlobStoringDatabaseDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<DatabaseBlobContainer>(b =>
{
b.ToTable(options.TablePrefix + "BlobContainers", options.Schema);
b.ConfigureByConvention();
b.Property(p => p.Name).IsRequired().HasMaxLength(DatabaseContainerConsts.MaxNameLength);
b.HasIndex(x => new {x.TenantId, x.Name});
});
builder.Entity<DatabaseBlob>(b =>
{
b.ToTable(options.TablePrefix + "Blobs", options.Schema);
b.ConfigureByConvention();
b.Property(p => p.ContainerId).IsRequired(); //TODO: Foreign key!
b.Property(p => p.Name).IsRequired().HasMaxLength(DatabaseBlobConsts.MaxNameLength);
b.Property(p => p.Content).HasMaxLength(DatabaseBlobConsts.MaxContentLength);
b.HasIndex(x => new {x.TenantId, x.ContainerId, x.Name});
});
}
}
}

18
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringModelBuilderConfigurationOptions.cs

@ -0,0 +1,18 @@
using JetBrains.Annotations;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public class BlobStoringModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{
public BlobStoringModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = "",
[CanBeNull] string schema = null)
: base(
tablePrefix,
schema)
{
}
}
}

23
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public class EfCoreDatabaseBlobContainerRepository : EfCoreRepository<IBlobStoringDbContext, DatabaseBlobContainer, Guid>, IDatabaseBlobContainerRepository
{
public EfCoreDatabaseBlobContainerRepository(IDbContextProvider<IBlobStoringDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<DatabaseBlobContainer> FindAsync(string name, CancellationToken cancellationToken = default)
{
return await DbSet.FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken));
}
}
}

53
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs

@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public class EfCoreDatabaseBlobRepository : EfCoreRepository<IBlobStoringDbContext, DatabaseBlob, Guid>, IDatabaseBlobRepository
{
public EfCoreDatabaseBlobRepository(IDbContextProvider<IBlobStoringDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<DatabaseBlob> FindAsync(
Guid containerId,
string name,
CancellationToken cancellationToken = default)
{
return await DbSet.FirstOrDefaultAsync(
x => x.ContainerId == containerId && x.Name == name,
GetCancellationToken(cancellationToken)
);
}
public virtual async Task<bool> ExistsAsync(
Guid containerId,
string name,
CancellationToken cancellationToken = default)
{
return await DbSet.AnyAsync(
x => x.ContainerId == containerId && x.Name == name,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> DeleteAsync(
Guid containerId,
string name,
CancellationToken cancellationToken = default)
{
var blob = await FindAsync(containerId, name, cancellationToken);
if (blob == null)
{
return false;
}
await base.DeleteAsync(blob.Id, cancellationToken: GetCancellationToken(cancellationToken));
return true;
}
}
}

14
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/IBlobStoringDbContext.cs

@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public interface IBlobStoringDbContext : IEfCoreDbContext
{
DbSet<DatabaseBlobContainer> BlobContainers { get; }
DbSet<DatabaseBlob> Blobs { get; }
}
}

3
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

16
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.MongoDB\Volo.Abp.MongoDB.csproj" />
<ProjectReference Include="..\Volo.Abp.BlobStoring.Database.Domain\Volo.Abp.BlobStoring.Database.Domain.csproj" />
</ItemGroup>
</Project>

22
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoDbModule.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[DependsOn(
typeof(BlobStoringDatabaseDomainModule),
typeof(AbpMongoDbModule)
)]
public class BlobStoringDatabaseMongoDbModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<BlobStoringMongoDbContext>(options =>
{
options.AddRepository<DatabaseBlobContainer, MongoDbDatabaseBlobContainerRepository>();
options.AddRepository<DatabaseBlob, MongoDbDatabaseBlobRepository>();
});
}
}
}

21
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContext.cs

@ -0,0 +1,21 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public class BlobStoringMongoDbContext : AbpMongoDbContext, IBlobStoringMongoDbContext
{
public IMongoCollection<DatabaseBlobContainer> BlobContainers => Collection<DatabaseBlobContainer>();
public IMongoCollection<DatabaseBlob> Blobs => Collection<DatabaseBlob>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.ConfigureBlobStoring();
}
}
}

31
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContextExtensions.cs

@ -0,0 +1,31 @@
using System;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public static class BlobStoringMongoDbContextExtensions
{
public static void ConfigureBlobStoring(
this IMongoModelBuilder builder,
Action<AbpMongoModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new BlobStoringMongoModelBuilderConfigurationOptions(
BlobStoringDatabaseDbProperties.DbTablePrefix
);
optionsAction?.Invoke(options);
builder.Entity<DatabaseBlobContainer>(b =>
{
b.CollectionName = options.CollectionPrefix + "BlobContainers";
});
builder.Entity<DatabaseBlob>(b =>
{
b.CollectionName = options.CollectionPrefix + "Blobs";
});
}
}
}

14
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoModelBuilderConfigurationOptions.cs

@ -0,0 +1,14 @@
using JetBrains.Annotations;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public class BlobStoringMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions
{
public BlobStoringMongoModelBuilderConfigurationOptions(
[NotNull] string collectionPrefix = "")
: base(collectionPrefix)
{
}
}
}

14
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/IBlobStoringMongoDbContext.cs

@ -0,0 +1,14 @@
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public interface IBlobStoringMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<DatabaseBlobContainer> BlobContainers { get; }
IMongoCollection<DatabaseBlob> Blobs { get; }
}
}

21
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobContainerRepository.cs

@ -0,0 +1,21 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public class MongoDbDatabaseBlobContainerRepository : MongoDbRepository<IBlobStoringMongoDbContext, DatabaseBlobContainer, Guid>, IDatabaseBlobContainerRepository
{
public MongoDbDatabaseBlobContainerRepository(IMongoDbContextProvider<IBlobStoringMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<DatabaseBlobContainer> FindAsync(string name, CancellationToken cancellationToken = default)
{
return await base.FindAsync(x => x.Name == name, cancellationToken: GetCancellationToken(cancellationToken));
}
}
}

45
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs

@ -0,0 +1,45 @@
using MongoDB.Driver.Linq;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public class MongoDbDatabaseBlobRepository : MongoDbRepository<IBlobStoringMongoDbContext, DatabaseBlob, Guid>, IDatabaseBlobRepository
{
public MongoDbDatabaseBlobRepository(IMongoDbContextProvider<IBlobStoringMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<DatabaseBlob> FindAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable().FirstOrDefaultAsync(
x => x.ContainerId == containerId &&
x.Name == name,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> ExistsAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable().AnyAsync(
x => x.ContainerId == containerId &&
x.Name == name,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> DeleteAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
var blob = await FindAsync(containerId, name, cancellationToken);
if (blob == null)
{
return false;
}
await base.DeleteAsync(blob, cancellationToken: GetCancellationToken(cancellationToken));
return true;
}
}
}

10
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/BlobStoringDatabaseDomainTestBase.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.BlobStoring.Database
{
/* Inherit from this class for your domain layer tests.
* See SampleManager_Tests for example.
*/
public abstract class BlobStoringDatabaseDomainTestBase : BlobStoringDatabaseTestBase<BlobStoringDatabaseDomainTestModule>
{
}
}

13
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/BlobStoringDatabaseDomainTestModule.cs

@ -0,0 +1,13 @@
using Volo.Abp.BlobStoring.Database.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Volo.Abp.BlobStoring.Database
{
[DependsOn(
typeof(BlobStoringDatabaseEntityFrameworkCoreTestModule)
)]
public class BlobStoringDatabaseDomainTestModule : AbpModule
{
}
}

13
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.csproj

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Volo.Abp.BlobStoring.Database</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<ProjectReference Include="..\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests\Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj" />
</ItemGroup>
</Project>

7
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestBase.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public abstract class BlobStoringDatabaseEntityFrameworkCoreTestBase : BlobStoringDatabaseTestBase<BlobStoringDatabaseEntityFrameworkCoreTestModule>
{
}
}

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

Loading…
Cancel
Save