diff --git a/docs/en/Blob-Storing-Database.md b/docs/en/Blob-Storing-Database.md index 9c81d5a82f..b413882227 100644 --- a/docs/en/Blob-Storing-Database.md +++ b/docs/en/Blob-Storing-Database.md @@ -1,3 +1,96 @@ # BLOB Storing Database Provider -TODO \ No newline at end of file +BLOB Storing Database Storage Provider can store BLOBs in a relational or non-relational database. + +There are two database providers implemented; + +* [Volo.Abp.BlobStoring.Database.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.EntityFrameworkCore) package implements for [EF Core](Entity-Framework-Core.md), so it can store BLOBs in [any DBMS supported](https://docs.microsoft.com/en-us/ef/core/providers/) by the EF Core. +* [Volo.Abp.BlobStoring.Database.MongoDB](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.MongoDB) package implements for [MongoDB](MongoDB.md). + +> Read the [BLOB Storing document](Blob-Storing.md) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a database as the storage provider. + +## Installation + +### Automatic Installation + +If you've created your solution based on the [application startup template](Startup-Templates/Application.md), you can use the `abp add-module` [CLI](CLI.md) command to automatically add related packages to your solution. + +Open a command prompt (terminal) in the folder containing your solution (`.sln`) file and run the following command: + +````bash +abp add-module Volo.Abp.BlobStoring.Database +```` + +This command adds all the NuGet packages to corresponding layers of your solution. If you are using EF Core, it adds necessary configuration, adds a new database migration and updates the database. + +### Manual Installation + +Here, all the NuGet packages defined by this provider; + +* [Volo.Abp.BlobStoring.Database.Domain.Shared](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Domain.Shared) +* [Volo.Abp.BlobStoring.Database.Domain](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.Domain) +* [Volo.Abp.BlobStoring.Database.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.EntityFrameworkCore) +* [Volo.Abp.BlobStoring.Database.MongoDB](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Database.MongoDB) + +You can only install Volo.Abp.BlobStoring.Database.EntityFrameworkCore or Volo.Abp.BlobStoring.Database.MongoDB (based on your preference) since they depends on the other packages. + +After installation, add `DepenedsOn` attribute to your related [module](Module-Development-Basics.md). Here, the list of module classes defined by the related NuGet packages listed above: + +* `BlobStoringDatabaseDomainModule` +* `BlobStoringDatabaseDomainSharedModule` +* `BlobStoringDatabaseEntityFrameworkCoreModule` +* `BlobStoringDatabaseMongoDbModule` + +Whenever you add a NuGet package to a project, also add the module class dependency. + +If you are using EF Core, you also need to configure your **Migration DbContext** to add BLOB storage tables to your database schema. Call `builder.ConfigureBlobStoring()` extension method inside the `OnModelCreating` method to include mappings to your DbContext. Then you can use the standard `Add-Migration` and `Update-Database` [commands](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create necessary tables in your database. + +## Configuration + +### Connection String + +If you will use your `Default` connection string, you don't need to any additional configuration. + +If you want to use a separate database for BLOB storage, use the `AbpBlobStoring` as the [connection string](Connection-Strings.md) name in your configuration file (`appsettings.json`). In this case, also read the [EF Core Migrations](Entity-Framework-Core-Migrations.md) document to learn how to create and use a different database for a desired module. + +### Configuring the Containers + +Configuration is done in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class, as explained in the [BLOB Storing document](Blob-Storing.md). + +**Example: Configure to use the database storage provider by default** + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseDatabase(); + }); +}); +```` + +> See the [BLOB Storing document](Blob-Storing.md) to learn how to configure this provider for a specific container. + +## Additional Information + +It is expected to use the [BLOB Storing services](Blob-Storing.md) to use the BLOB storing system. However, if you want to work on the database tables/entities, you can use the following information. + +### Entities + +Entities defined for this module: + +* `DatabaseBlobContainer` (aggregate root) represents a container stored in the database. +* `DatabaseBlob` (aggregate root) represents a BLOB in the database. + +See the [entities document](Entities.md) to learn what is an entity and aggregate root. + +### Repositories + +* `IDatabaseBlobContainerRepository` +* `IDatabaseBlobRepository` + +You can also use `IRepository` and `IRepository` to take the power of IQueryable. See the [repository document](Repositories.md) for more. + +### Other Services + +* `DatabaseBlobProvider` is the main service that implements the database BLOB storage provider, if you want to override/replace it via [dependency injection](Dependency-Injection.md) (don't replace `IBlobProvider` interface, but replace `DatabaseBlobProvider` class). \ No newline at end of file diff --git a/docs/en/Connection-Strings.md b/docs/en/Connection-Strings.md index eb7aae3a21..585d0657f2 100644 --- a/docs/en/Connection-Strings.md +++ b/docs/en/Connection-Strings.md @@ -72,7 +72,7 @@ Relational databases require to create the database and the database schema (tab The startup template (with EF Core ORM) comes with a single database and a `.EntityFrameworkCore.DbMigrations` project that contains the migration files for that database. This project mainly defines a *YourProjectName*MigrationsDbContext that calls the `Configure...()` methods of the used modules, like `builder.ConfigurePermissionManagement()`. -Once you want to separate a module's database, you typically will need to create a second migration path. The easiest way to create a copy of the `.EntityFrameworkCore.DbMigrations` project with the `DbContext` inside it, change its content to only call the `Configure...()` methods of the modules needs to be stored in the second database and re-create the initial migration. In this case, you also need to change the `.DbMigrator` application to be able to work with these second database too. In this way, you will have a separate migrations DbContext per database. +Once you want to separate a module's database, you typically will need to create a second migration path. See the [EF Core Migrations](Entity-Framework-Core-Migrations.md) document to learn how to create and use a different database for a desired module. ## Multi-Tenancy diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml index 76c14746af..21ea8a7a44 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml @@ -34,7 +34,7 @@

Borders

-

Based on Bootstrap Border.

+

Based on Bootstrap Border.

Border

@@ -145,7 +145,7 @@ <span abp-border="Top_Secondary"></span> <span abp-border="Right_Success"></span> <span abp-border="Bottom_Danger"></span> -<span abp-border="bottom_Warning"></span> +<span abp-border="Bottom_Warning"></span> <span abp-border="Left_Info"></span> <span abp-border="Top_Light"></span> <span abp-border="Right_Dark"></span> @@ -212,4 +212,4 @@ - \ No newline at end of file + diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs index 3edf68b053..fbccdb067e 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs @@ -26,8 +26,11 @@ namespace Volo.Abp.BlobStoring.Database { var container = await GetOrCreateContainerAsync(args.ContainerName, args.CancellationToken); - var blob = await DatabaseBlobRepository.FindAsync(container.Id, args.BlobName, - args.CancellationToken); + var blob = await DatabaseBlobRepository.FindAsync( + container.Id, + args.BlobName, + args.CancellationToken + ); var content = await args.BlobStream.GetAllBytesAsync(args.CancellationToken); @@ -40,58 +43,72 @@ namespace Volo.Abp.BlobStoring.Database } blob.SetContent(content); - await DatabaseBlobRepository.UpdateAsync(blob); + + await DatabaseBlobRepository.UpdateAsync(blob, autoSave: true); } else { blob = new DatabaseBlob(GuidGenerator.Create(), container.Id, args.BlobName, content); - await DatabaseBlobRepository.InsertAsync(blob); + await DatabaseBlobRepository.InsertAsync(blob, autoSave: true); } } public override async Task DeleteAsync(BlobProviderDeleteArgs args) { - var container = - await DatabaseBlobContainerRepository.FindAsync(args.ContainerName, - args.CancellationToken); + var container = await DatabaseBlobContainerRepository.FindAsync( + args.ContainerName, + args.CancellationToken + ); if (container == null) { return false; } - return await DatabaseBlobRepository.DeleteAsync(container.Id, args.BlobName, - args.CancellationToken); + return await DatabaseBlobRepository.DeleteAsync( + container.Id, + args.BlobName, + autoSave: true, + cancellationToken: args.CancellationToken + ); } public override async Task ExistsAsync(BlobProviderExistsArgs args) { - var container = - await DatabaseBlobContainerRepository.FindAsync(args.ContainerName, - args.CancellationToken); + var container = await DatabaseBlobContainerRepository.FindAsync( + args.ContainerName, + args.CancellationToken + ); if (container == null) { return false; } - return await DatabaseBlobRepository.ExistsAsync(container.Id, args.BlobName, - args.CancellationToken); + return await DatabaseBlobRepository.ExistsAsync( + container.Id, + args.BlobName, + args.CancellationToken + ); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { - var container = - await DatabaseBlobContainerRepository.FindAsync(args.ContainerName, - args.CancellationToken); + 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); + var blob = await DatabaseBlobRepository.FindAsync( + container.Id, + args.BlobName, + args.CancellationToken + ); if (blob == null) { diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs index 06afcfd28c..e3b96805c2 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs @@ -12,6 +12,6 @@ namespace Volo.Abp.BlobStoring.Database Task ExistsAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default); - Task DeleteAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default); + Task DeleteAsync(Guid containerId, [NotNull] string name, bool autoSave = false, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs index f4d1a83466..098f6095e4 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs @@ -7,9 +7,10 @@ using Volo.Abp.EntityFrameworkCore; namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore { - public class EfCoreDatabaseBlobRepository : EfCoreRepository, IDatabaseBlobRepository + public class EfCoreDatabaseBlobRepository : EfCoreRepository, + IDatabaseBlobRepository { - public EfCoreDatabaseBlobRepository(IDbContextProvider dbContextProvider) + public EfCoreDatabaseBlobRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { } @@ -38,15 +39,18 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore public virtual async Task DeleteAsync( Guid containerId, string name, + bool autoSave = false, CancellationToken cancellationToken = default) { + //TODO: Should extract this logic to out of the repository and remove this method completely + var blob = await FindAsync(containerId, name, cancellationToken); if (blob == null) { return false; } - await base.DeleteAsync(blob.Id, cancellationToken: GetCancellationToken(cancellationToken)); + await base.DeleteAsync(blob, autoSave, cancellationToken: GetCancellationToken(cancellationToken)); return true; } } diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs index 60d9e3d148..6c5b034fc1 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs @@ -29,7 +29,11 @@ namespace Volo.Abp.BlobStoring.Database.MongoDB GetCancellationToken(cancellationToken)); } - public virtual async Task DeleteAsync(Guid containerId, string name, CancellationToken cancellationToken = default) + public virtual async Task DeleteAsync( + Guid containerId, + string name, + bool autoSave = false, + CancellationToken cancellationToken = default) { var blob = await FindAsync(containerId, name, cancellationToken); @@ -38,7 +42,7 @@ namespace Volo.Abp.BlobStoring.Database.MongoDB return false; } - await base.DeleteAsync(blob, cancellationToken: GetCancellationToken(cancellationToken)); + await base.DeleteAsync(blob, autoSave, cancellationToken: GetCancellationToken(cancellationToken)); return true; } }