Merge branch 'master' into dev

pull/4308/head
Halil İbrahim Kalkan 5 years ago
commit 0343ed5a23

@ -1,3 +1,96 @@
# BLOB Storing Database Provider
TODO
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<AbpBlobStoringOptions>(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<DatabaseBlobContainer, Guid>` and `IRepository<DatabaseBlob, Guid>` 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).

@ -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

@ -34,7 +34,7 @@
<h2>Borders</h2>
<p>Based on <a href="https://getbootstrap.com/docs/4.1/components/border/" target="_blank"> Bootstrap Border</a>.</p>
<p>Based on <a href="https://getbootstrap.com/docs/4.1/utilities/borders/" target="_blank"> Bootstrap Border</a>.</p>
<h4>Border</h4>
@ -145,7 +145,7 @@
&lt;span abp-border=&quot;Top_Secondary&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Right_Success&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Bottom_Danger&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;bottom_Warning&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Bottom_Warning&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Left_Info&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Top_Light&quot;&gt;&lt;/span&gt;
&lt;span abp-border=&quot;Right_Dark&quot;&gt;&lt;/span&gt;

@ -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<bool> 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<bool> 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<Stream> 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)
{

@ -12,6 +12,6 @@ namespace Volo.Abp.BlobStoring.Database
Task<bool> ExistsAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(Guid containerId, [NotNull] string name, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(Guid containerId, [NotNull] string name, bool autoSave = false, CancellationToken cancellationToken = default);
}
}

@ -7,7 +7,8 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public class EfCoreDatabaseBlobRepository : EfCoreRepository<IBlobStoringDbContext, DatabaseBlob, Guid>, IDatabaseBlobRepository
public class EfCoreDatabaseBlobRepository : EfCoreRepository<IBlobStoringDbContext, DatabaseBlob, Guid>,
IDatabaseBlobRepository
{
public EfCoreDatabaseBlobRepository(IDbContextProvider<IBlobStoringDbContext> dbContextProvider)
: base(dbContextProvider)
@ -38,15 +39,18 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
public virtual async Task<bool> 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;
}
}

@ -29,7 +29,11 @@ namespace Volo.Abp.BlobStoring.Database.MongoDB
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> DeleteAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
public virtual async Task<bool> 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;
}
}

Loading…
Cancel
Save