Browse Source

Merge remote-tracking branch 'abpframework/dev' into docs

pull/4159/head
liangshiwei 6 years ago
parent
commit
44b5413cf4
  1. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs
  2. 64
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  3. 12
      framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/DefaultBlobFilePathCalculator.cs
  4. 113
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainer.cs
  5. 7
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs
  6. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderDeleteArgs.cs
  7. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderExistsArgs.cs
  8. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderGetArgs.cs
  9. 5
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderSaveArgs.cs
  10. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Services/IDomainService.cs
  11. 16
      framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/BlogFilePathCalculator_Tests.cs
  12. 4
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.csproj
  13. 9
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobConsts.cs
  14. 4
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobStoringDatabaseDomainSharedModule.cs
  15. 15
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseBlobConsts.cs
  16. 2
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/DatabaseContainerConsts.cs
  17. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/cs.json
  18. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/en.json
  19. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pl-PL.json
  20. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/pt-BR.json
  21. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/sl.json
  22. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/tr.json
  23. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/vi.json
  24. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hans.json
  25. 0
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/zh-Hant.json
  26. 10
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlob.cs
  27. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainer.cs
  28. 23
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainerConfigurationExtensions.cs
  29. 77
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProvider.cs
  30. 12
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobProviderConfiguration.cs
  31. 17
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IBlobRepository.cs
  32. 15
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IContainerRepository.cs
  33. 13
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobContainerRepository.cs
  34. 17
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/IDatabaseBlobRepository.cs
  35. 47
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseDbContextModelCreatingExtensions.cs
  36. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreModule.cs
  37. 11
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContext.cs
  38. 47
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContextModelCreatingExtensions.cs
  39. 4
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringModelBuilderConfigurationOptions.cs
  40. 47
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreBlobRepository.cs
  41. 37
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreContainerRepository.cs
  42. 23
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobContainerRepository.cs
  43. 53
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreDatabaseBlobRepository.cs
  44. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/IBlobStoringDbContext.cs
  45. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoDbModule.cs
  46. 8
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContext.cs
  47. 12
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContextExtensions.cs
  48. 4
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoModelBuilderConfigurationOptions.cs
  49. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/IBlobStoringMongoDbContext.cs
  50. 35
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbContainerRepository.cs
  51. 21
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobContainerRepository.cs
  52. 18
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs
  53. 4
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs
  54. 7
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/EfCoreContainer_Test.cs
  55. 7
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/EfCoreContainer_Tests.cs
  56. 10
      modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbContainer_Tests.cs

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;
}
}
}

64
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,7 @@
(function ($) {
abp.dom = abp.dom || {};
abp.dom.initializers = abp.dom.initializers || {};
abp.dom.initializers.initializeForms = function ($forms, validate) {
@ -70,10 +71,68 @@
$timeagos.timeago();
}
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();
});
});
}
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);
});
@ -84,10 +143,15 @@
});
});
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();
});

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));

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
{

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
);
}
}

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

@ -13,8 +13,8 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\BlobStoring\Database\Localization\Database\*.json" />
<Content Remove="Volo\Abp\BlobStoring\Database\Localization\Database\*.json" />
<EmbeddedResource Include="Volo\Abp\BlobStoring\Database\Localization\*.json" />
<Content Remove="Volo\Abp\BlobStoring\Database\Localization\*.json" />
</ItemGroup>
</Project>

9
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/BlobConsts.cs

@ -1,9 +0,0 @@
namespace Volo.Abp.BlobStoring.Database
{
public static class BlobConsts
{
public const int MaxNameLength = 256;
public const int MaxContentLength = 2_000_000_000; // 2 GB
}
}

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

@ -17,7 +17,7 @@ namespace Volo.Abp.BlobStoring.Database
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BlobStoringDatabaseDomainSharedModule>("Volo.Abp.BlobStoring.Database");
options.FileSets.AddEmbedded<BlobStoringDatabaseDomainSharedModule>();
});
Configure<AbpLocalizationOptions>(options =>
@ -25,7 +25,7 @@ namespace Volo.Abp.BlobStoring.Database
options.Resources
.Add<BlobStoringDatabaseResource>("en")
.AddBaseTypes(typeof(AbpValidationResource))
.AddVirtualJson("/Localization/BlobStoringDatabase");
.AddVirtualJson("/Volo/Abp/BlobStoring/Database/Localization");
});
Configure<AbpExceptionLocalizationOptions>(options =>

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;
}
}

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

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

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

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

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

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

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

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

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

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

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

10
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/Blob.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlob.cs

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

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/Container.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo/Abp/BlobStoring/Database/DatabaseBlobContainer.cs

@ -5,16 +5,16 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BlobStoring.Database
{
public class Container : AggregateRoot<Guid>, IMultiTenant //TODO: Rename to BlobContainer
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 Container(Guid id, [NotNull] string name, Guid? tenantId = null)
public DatabaseBlobContainer(Guid id, [NotNull] string name, Guid? tenantId = null)
: base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), ContainerConsts.MaxNameLength);
Name = Check.NotNullOrWhiteSpace(name, nameof(name), DatabaseContainerConsts.MaxNameLength);
TenantId = tenantId;
}
}

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

@ -1,30 +1,11 @@
using System;
namespace Volo.Abp.BlobStoring.Database
namespace Volo.Abp.BlobStoring.Database
{
public static class DatabaseBlobContainerConfigurationExtensions
{
public static DatabaseBlobProviderConfiguration GetDatabaseConfiguration(
this BlobContainerConfiguration containerConfiguration)
{
return new DatabaseBlobProviderConfiguration(containerConfiguration);
}
public static BlobContainerConfiguration UseDatabase(
this BlobContainerConfiguration containerConfiguration,
Action<DatabaseBlobProviderConfiguration> databaseConfigureAction)
{
containerConfiguration.ProviderType = typeof(DatabaseBlobProvider);
databaseConfigureAction(new DatabaseBlobProviderConfiguration(containerConfiguration));
return containerConfiguration;
}
public static BlobContainerConfiguration UseDatabase(this BlobContainerConfiguration containerConfiguration)
this BlobContainerConfiguration containerConfiguration)
{
containerConfiguration.ProviderType = typeof(DatabaseBlobProvider);
return containerConfiguration;
}
}

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

@ -1,26 +1,33 @@
using System;
using System.IO;
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 IBlobRepository BlobRepository { get; }
protected IContainerRepository ContainerRepository { get; }
public DatabaseBlobProvider(IBlobRepository blobRepository, IContainerRepository containerRepository)
protected IDatabaseBlobRepository DatabaseBlobRepository { get; }
protected IDatabaseBlobContainerRepository DatabaseBlobContainerRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public DatabaseBlobProvider(
IDatabaseBlobRepository databaseBlobRepository,
IDatabaseBlobContainerRepository databaseBlobContainerRepository,
IGuidGenerator guidGenerator)
{
BlobRepository = blobRepository;
ContainerRepository = containerRepository;
DatabaseBlobRepository = databaseBlobRepository;
DatabaseBlobContainerRepository = databaseBlobContainerRepository;
GuidGenerator = guidGenerator;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
{
var container = await ContainerRepository.CreateIfNotExistAsync(args.ContainerName, args.TenantId, args.CancellationToken);
var blob = await BlobRepository.FindAsync(container.Id, args.BlobName, args.TenantId, args.CancellationToken);
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);
@ -28,53 +35,63 @@ namespace Volo.Abp.BlobStoring.Database
{
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.");
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 BlobRepository.UpdateAsync(blob);
await DatabaseBlobRepository.UpdateAsync(blob);
}
else
{
blob = new Blob(Guid.NewGuid(), container.Id, args.BlobName, content, args.TenantId);
await BlobRepository.InsertAsync(blob);
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 ContainerRepository.FindAsync(args.ContainerName, args.TenantId, args.CancellationToken);
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return false;
}
return await BlobRepository.DeleteAsync(container.Id, args.BlobName, args.TenantId, args.CancellationToken);
return await DatabaseBlobRepository.DeleteAsync(container.Id, args.BlobName,
args.CancellationToken);
}
public override async Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
var container = await ContainerRepository.FindAsync(args.ContainerName, args.TenantId, args.CancellationToken);
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return false;
}
return await BlobRepository.ExistsAsync(container.Id, args.BlobName, args.TenantId, args.CancellationToken);
return await DatabaseBlobRepository.ExistsAsync(container.Id, args.BlobName,
args.CancellationToken);
}
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
var container = await ContainerRepository.FindAsync(args.ContainerName, args.TenantId, args.CancellationToken);
var container =
await DatabaseBlobContainerRepository.FindAsync(args.ContainerName,
args.CancellationToken);
if (container == null)
{
return null;
}
var blob = await BlobRepository.FindAsync(container.Id, args.BlobName, args.TenantId, args.CancellationToken);
var blob = await DatabaseBlobRepository.FindAsync(container.Id, args.BlobName,
args.CancellationToken);
if (blob == null)
{
@ -83,5 +100,21 @@ namespace Volo.Abp.BlobStoring.Database
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;
}
}
}

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

@ -1,12 +0,0 @@
namespace Volo.Abp.BlobStoring.Database
{
public class DatabaseBlobProviderConfiguration
{
private readonly BlobContainerConfiguration _containerConfiguration;
public DatabaseBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
{
_containerConfiguration = containerConfiguration;
}
}
}

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

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

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

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

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);
}
}

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

@ -1,47 +0,0 @@
using Microsoft.EntityFrameworkCore;
using System;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public static class BlobStoringDatabaseDbContextModelCreatingExtensions
{
public static void ConfigureDatabaseBlobStoring(
this ModelBuilder builder,
Action<BlobStoringDatabaseModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new BlobStoringDatabaseModelBuilderConfigurationOptions(
BlobStoringDatabaseDbProperties.DbTablePrefix,
BlobStoringDatabaseDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<Container>(b =>
{
b.ToTable(options.TablePrefix + "Containers", options.Schema);
b.ConfigureByConvention();
b.Property(p => p.Name).IsRequired().HasMaxLength(ContainerConsts.MaxNameLength);
b.HasIndex(x => x.Name);
});
builder.Entity<Blob>(b =>
{
b.ToTable(options.TablePrefix + "Blobs", options.Schema);
b.ConfigureByConvention();
b.Property(p => p.Name).IsRequired().HasMaxLength(BlobConsts.MaxNameLength);
b.Property(p => p.ContainerId).IsRequired();
b.Property(p => p.Content).HasMaxLength(BlobConsts.MaxContentLength);
b.HasIndex(x => x.Name);
});
}
}
}

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

@ -12,11 +12,11 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<BlobStoringDatabaseDbContext>(options =>
context.Services.AddAbpDbContext<BlobStoringDbContext>(options =>
{
options.AddRepository<Container, EfCoreContainerRepository>();
options.AddRepository<DatabaseBlobContainer, EfCoreDatabaseBlobContainerRepository>();
options.AddRepository<Blob, EfCoreBlobRepository>();
options.AddRepository<DatabaseBlob, EfCoreDatabaseBlobRepository>();
});
}
}

11
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseDbContext.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDbContext.cs

@ -5,13 +5,13 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public class BlobStoringDatabaseDbContext : AbpDbContext<BlobStoringDatabaseDbContext>, IBlobStoringDatabaseDbContext
public class BlobStoringDbContext : AbpDbContext<BlobStoringDbContext>, IBlobStoringDbContext
{
public DbSet<Container> Containers { get; set; }
public DbSet<DatabaseBlobContainer> BlobContainers { get; set; }
public DbSet<Blob> Blobs { get; set; }
public DbSet<DatabaseBlob> Blobs { get; set; }
public BlobStoringDatabaseDbContext(DbContextOptions<BlobStoringDatabaseDbContext> options)
public BlobStoringDbContext(DbContextOptions<BlobStoringDbContext> options)
: base(options)
{
@ -21,8 +21,7 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
base.OnModelCreating(builder);
builder.ConfigureDatabaseBlobStoring();
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});
});
}
}
}

4
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringDatabaseModelBuilderConfigurationOptions.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/BlobStoringModelBuilderConfigurationOptions.cs

@ -3,9 +3,9 @@ using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
public class BlobStoringDatabaseModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
public class BlobStoringModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{
public BlobStoringDatabaseModelBuilderConfigurationOptions(
public BlobStoringModelBuilderConfigurationOptions(
[NotNull] string tablePrefix = "",
[CanBeNull] string schema = null)
: base(

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

@ -1,47 +0,0 @@
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 EfCoreBlobRepository : EfCoreRepository<IBlobStoringDatabaseDbContext, Blob, Guid>, IBlobRepository
{
public EfCoreBlobRepository(IDbContextProvider<IBlobStoringDatabaseDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Blob> FindAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
return await DbSet.FirstOrDefaultAsync(
x => x.ContainerId == containerId &&
x.Name == name &&
x.TenantId == tenantId,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> ExistsAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
return await DbSet.AnyAsync(
x => x.ContainerId == containerId &&
x.Name == name &&
x.TenantId == tenantId,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> DeleteAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
var blob = await FindAsync(containerId, name, tenantId, cancellationToken);
if (blob == null)
{
return false;
}
await base.DeleteAsync(blob.Id, cancellationToken: GetCancellationToken(cancellationToken));
return true;
}
}
}

37
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/EfCoreContainerRepository.cs

@ -1,37 +0,0 @@
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 EfCoreContainerRepository : EfCoreRepository<IBlobStoringDatabaseDbContext, Container, Guid>, IContainerRepository
{
public EfCoreContainerRepository(IDbContextProvider<IBlobStoringDatabaseDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Container> CreateIfNotExistAsync(string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
var container = await FindAsync(name, tenantId, cancellationToken);
if (container != null)
{
return container;
}
container = new Container(Guid.NewGuid(), name, tenantId);
await base.InsertAsync(container, true, GetCancellationToken(cancellationToken));
return container;
}
public virtual async Task<Container> FindAsync(string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
return await DbSet.WhereIf(tenantId != null, x => x.TenantId == tenantId)
.FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken));
}
}
}

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;
}
}
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/IBlobStoringDatabaseDbContext.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo/Abp/BlobStoring/Database/EntityFrameworkCore/IBlobStoringDbContext.cs

@ -5,10 +5,10 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public interface IBlobStoringDatabaseDbContext : IEfCoreDbContext
public interface IBlobStoringDbContext : IEfCoreDbContext
{
DbSet<Container> Containers { get; }
DbSet<DatabaseBlobContainer> BlobContainers { get; }
DbSet<Blob> Blobs { get; }
DbSet<DatabaseBlob> Blobs { get; }
}
}

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

@ -12,10 +12,10 @@ namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<BlobStoringDatabaseMongoDbContext>(options =>
context.Services.AddMongoDbContext<BlobStoringMongoDbContext>(options =>
{
options.AddRepository<Container, MongoDbContainerRepository>();
options.AddRepository<Blob, MongoDbBlobRepository>();
options.AddRepository<DatabaseBlobContainer, MongoDbDatabaseBlobContainerRepository>();
options.AddRepository<DatabaseBlob, MongoDbDatabaseBlobRepository>();
});
}
}

8
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoDbContext.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContext.cs

@ -5,17 +5,17 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public class BlobStoringDatabaseMongoDbContext : AbpMongoDbContext, IBlobStoringDatabaseMongoDbContext
public class BlobStoringMongoDbContext : AbpMongoDbContext, IBlobStoringMongoDbContext
{
public IMongoCollection<Container> Containers => Collection<Container>();
public IMongoCollection<DatabaseBlobContainer> BlobContainers => Collection<DatabaseBlobContainer>();
public IMongoCollection<Blob> Blobs => Collection<Blob>();
public IMongoCollection<DatabaseBlob> Blobs => Collection<DatabaseBlob>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.ConfigureDatabaseBlobStoring();
modelBuilder.ConfigureBlobStoring();
}
}
}

12
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoDbContextExtensions.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoDbContextExtensions.cs

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

4
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringDatabaseMongoModelBuilderConfigurationOptions.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/BlobStoringMongoModelBuilderConfigurationOptions.cs

@ -3,9 +3,9 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public class BlobStoringDatabaseMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions
public class BlobStoringMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions
{
public BlobStoringDatabaseMongoModelBuilderConfigurationOptions(
public BlobStoringMongoModelBuilderConfigurationOptions(
[NotNull] string collectionPrefix = "")
: base(collectionPrefix)
{

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/IBlobStoringDatabaseMongoDbContext.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/IBlobStoringMongoDbContext.cs

@ -5,10 +5,10 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[ConnectionStringName(BlobStoringDatabaseDbProperties.ConnectionStringName)]
public interface IBlobStoringDatabaseMongoDbContext : IAbpMongoDbContext
public interface IBlobStoringMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<Container> Containers { get; }
IMongoCollection<DatabaseBlobContainer> BlobContainers { get; }
IMongoCollection<Blob> Blobs { get; }
IMongoCollection<DatabaseBlob> Blobs { get; }
}
}

35
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbContainerRepository.cs

@ -1,35 +0,0 @@
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 MongoDbContainerRepository : MongoDbRepository<IBlobStoringDatabaseMongoDbContext, Container, Guid>, IContainerRepository
{
public MongoDbContainerRepository(IMongoDbContextProvider<IBlobStoringDatabaseMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Container> CreateIfNotExistAsync(string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
var container = await FindAsync(name, tenantId, cancellationToken);
if (container != null)
{
return container;
}
container = new Container(Guid.NewGuid(), name, tenantId);
await InsertAsync(container, true, GetCancellationToken(cancellationToken));
return container;
}
public virtual async Task<Container> FindAsync(string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
{
return await base.FindAsync(x => x.Name == name, cancellationToken: GetCancellationToken(cancellationToken));
}
}
}

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));
}
}
}

18
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbBlobRepository.cs → modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs

@ -7,33 +7,31 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
public class MongoDbBlobRepository : MongoDbRepository<IBlobStoringDatabaseMongoDbContext, Blob, Guid>, IBlobRepository
public class MongoDbDatabaseBlobRepository : MongoDbRepository<IBlobStoringMongoDbContext, DatabaseBlob, Guid>, IDatabaseBlobRepository
{
public MongoDbBlobRepository(IMongoDbContextProvider<IBlobStoringDatabaseMongoDbContext> dbContextProvider) : base(dbContextProvider)
public MongoDbDatabaseBlobRepository(IMongoDbContextProvider<IBlobStoringMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Blob> FindAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
public virtual async Task<DatabaseBlob> FindAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable().FirstOrDefaultAsync(
x => x.ContainerId == containerId &&
x.Name == name &&
x.TenantId == tenantId,
x.Name == name,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> ExistsAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
public virtual async Task<bool> ExistsAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
return await GetMongoQueryable().AnyAsync(
x => x.ContainerId == containerId &&
x.Name == name &&
x.TenantId == tenantId,
x.Name == name,
GetCancellationToken(cancellationToken));
}
public virtual async Task<bool> DeleteAsync(Guid containerId, string name, Guid? tenantId = null, CancellationToken cancellationToken = default)
public virtual async Task<bool> DeleteAsync(Guid containerId, string name, CancellationToken cancellationToken = default)
{
var blob = await FindAsync(containerId, name, tenantId, cancellationToken);
var blob = await FindAsync(containerId, name, cancellationToken);
if (blob == null)
{

4
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs

@ -31,8 +31,8 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
new BlobStoringDatabaseDbContext(
new DbContextOptionsBuilder<BlobStoringDatabaseDbContext>().UseSqlite(connection).Options
new BlobStoringDbContext(
new DbContextOptionsBuilder<BlobStoringDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables();
return connection;

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

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

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

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

10
modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbContainer_Tests.cs

@ -0,0 +1,10 @@
using Xunit;
namespace Volo.Abp.BlobStoring.Database.MongoDB
{
[Collection(MongoTestCollection.Name)]
public class MongoDbContainer_Tests : BlobContainer_Tests<BlobStoringDatabaseMongoDbTestModule>
{
}
}
Loading…
Cancel
Save