diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs index 1e6cd6f54c..9f2bf33a40 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; +using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories.MemoryDb { public interface IMemoryDatabase { - List Collection(); + IMemoryDatabaseCollection Collection() where TEntity : class, IEntity; TKey GenerateNextId(); } diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabaseCollection.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabaseCollection.cs new file mode 100644 index 0000000000..a2f4d5f270 --- /dev/null +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabaseCollection.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Domain.Repositories.MemoryDb +{ + public interface IMemoryDatabaseCollection : IEnumerable + { + void Add(TEntity entity); + + void Update(TEntity entity); + + void Remove(TEntity entity); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs index dd241b25a5..c179b68931 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs @@ -8,7 +8,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { IMemoryDatabase Database { get; } - List Collection { get; } + IMemoryDatabaseCollection Collection { get; } } public interface IMemoryDbRepository : IMemoryDbRepository, IRepository diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbSerializer.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbSerializer.cs new file mode 100644 index 0000000000..2854a7893f --- /dev/null +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbSerializer.cs @@ -0,0 +1,11 @@ +using System; + +namespace Volo.Abp.Domain.Repositories.MemoryDb +{ + public interface IMemoryDbSerializer + { + byte[] Serialize(object obj); + + object Deserialize(byte[] value, Type type); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs index be16beef85..6c2aa1417c 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs @@ -1,24 +1,33 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories.MemoryDb { - public class MemoryDatabase : IMemoryDatabase + public class MemoryDatabase : IMemoryDatabase, ITransientDependency { private readonly ConcurrentDictionary _sets; private readonly ConcurrentDictionary _entityIdGenerators; - public MemoryDatabase() + private readonly IServiceProvider _serviceProvider; + + public MemoryDatabase(IServiceProvider serviceProvider) { + _serviceProvider = serviceProvider; _sets = new ConcurrentDictionary(); _entityIdGenerators = new ConcurrentDictionary(); } - public List Collection() + public IMemoryDatabaseCollection Collection() + where TEntity : class, IEntity { - return _sets.GetOrAdd(typeof(TEntity), _ => new List()) as List; + return _sets.GetOrAdd(typeof(TEntity), + _ => _serviceProvider.GetRequiredService>()) as + IMemoryDatabaseCollection; } public TKey GenerateNextId() diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseCollection.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseCollection.cs new file mode 100644 index 0000000000..11c7f992a9 --- /dev/null +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseCollection.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.Domain.Repositories.MemoryDb +{ + public class MemoryDatabaseCollection : IMemoryDatabaseCollection + where TEntity : class, IEntity + { + private readonly Dictionary _dictionary = new Dictionary(); + + private readonly IMemoryDbSerializer _memoryDbSerializer; + + public MemoryDatabaseCollection(IMemoryDbSerializer memoryDbSerializer) + { + _memoryDbSerializer = memoryDbSerializer; + } + + public IEnumerator GetEnumerator() + { + foreach (var entity in _dictionary.Values) + { + yield return _memoryDbSerializer.Deserialize(entity, typeof(TEntity)).As(); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(TEntity entity) + { + _dictionary.Add(GetEntityKey(entity), _memoryDbSerializer.Serialize(entity)); + } + + public void Update(TEntity entity) + { + if (_dictionary.ContainsKey(GetEntityKey(entity))) + { + _dictionary[GetEntityKey(entity)] = _memoryDbSerializer.Serialize(entity); + } + } + + public void Remove(TEntity entity) + { + _dictionary.Remove(GetEntityKey(entity)); + } + + private string GetEntityKey(TEntity entity) + { + return entity.GetKeys().JoinAsString(","); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseManager.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseManager.cs index 4926abebf3..7507f3d625 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseManager.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseManager.cs @@ -1,19 +1,25 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; namespace Volo.Abp.Domain.Repositories.MemoryDb { - public static class MemoryDatabaseManager + public class MemoryDatabaseManager : ISingletonDependency { - private static ConcurrentDictionary _databases; + private readonly ConcurrentDictionary _databases = + new ConcurrentDictionary(); - static MemoryDatabaseManager() + private readonly IServiceProvider _serviceProvider; + + public MemoryDatabaseManager(IServiceProvider serviceProvider) { - _databases = new ConcurrentDictionary(); + _serviceProvider = serviceProvider; } - public static IMemoryDatabase Get(string databaseName) + public IMemoryDatabase Get(string databaseName) { - return _databases.GetOrAdd(databaseName, _ => new MemoryDatabase()); + return _databases.GetOrAdd(databaseName, _ => _serviceProvider.GetRequiredService()); } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index c658a34ef4..0f82aa798b 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { //TODO: Add dbcontext just like mongodb implementation! - public virtual List Collection => Database.Collection(); + public virtual IMemoryDatabaseCollection Collection => Database.Collection(); public virtual IMemoryDatabase Database => DatabaseProvider.GetDatabase(); @@ -33,6 +33,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb public override TEntity Update(TEntity entity, bool autoSave = false) { + Collection.Update(entity); return entity; } @@ -48,7 +49,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb public override long GetCount() { - return Collection.Count; + return Collection.Count(); } protected override IQueryable GetQueryable() diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs new file mode 100644 index 0000000000..9964e6219b --- /dev/null +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs @@ -0,0 +1,27 @@ +using System; +using System.Text; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace Volo.Abp.Domain.Repositories.MemoryDb +{ + public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency + { + private readonly IJsonSerializer _jsonSerializer; + + public Utf8JsonMemoryDbSerializer(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + + byte[] IMemoryDbSerializer.Serialize(object obj) + { + return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj)); + } + + public object Deserialize(byte[] value, Type type) + { + return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value)); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs index 6f940ca146..1547a581e5 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs @@ -13,7 +13,7 @@ namespace Volo.Abp.Domain.Repositories return repository.ToMemoryDbRepository().Database; } - public static List GetCollection(this IBasicRepository repository) + public static IMemoryDatabaseCollection GetCollection(this IBasicRepository repository) where TEntity : class, IEntity { return repository.ToMemoryDbRepository().Collection; diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs index d4f679a5b7..bd8b4b98a4 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs @@ -1,19 +1,19 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; +using Volo.Abp.Domain.Repositories.MemoryDb; +using Volo.Abp.Json; using Volo.Abp.Modularity; using Volo.Abp.Uow.MemoryDb; namespace Volo.Abp.MemoryDb { - /* TODO: Consider to store objects as binary serialized in the memory, which makes unit tests more realistic. - */ - [DependsOn(typeof(AbpDddDomainModule))] public class AbpMemoryDbModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.TryAddTransient(typeof(IMemoryDatabaseProvider<>), typeof(UnitOfWorkMemoryDatabaseProvider<>)); + context.Services.TryAddTransient(typeof(IMemoryDatabaseCollection<>), typeof(MemoryDatabaseCollection<>)); } } } diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs index 386ec77b12..24c1cdaeb9 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs @@ -11,15 +11,18 @@ namespace Volo.Abp.Uow.MemoryDb private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IConnectionStringResolver _connectionStringResolver; + private readonly MemoryDatabaseManager _memoryDatabaseManager; public UnitOfWorkMemoryDatabaseProvider( IUnitOfWorkManager unitOfWorkManager, IConnectionStringResolver connectionStringResolver, - TMemoryDbContext dbContext) + TMemoryDbContext dbContext, + MemoryDatabaseManager memoryDatabaseManager) { _unitOfWorkManager = unitOfWorkManager; _connectionStringResolver = connectionStringResolver; DbContext = dbContext; + _memoryDatabaseManager = memoryDatabaseManager; } public IMemoryDatabase GetDatabase() @@ -36,7 +39,7 @@ namespace Volo.Abp.Uow.MemoryDb var databaseApi = unitOfWork.GetOrAddDatabaseApi( dbContextKey, () => new MemoryDbDatabaseApi( - MemoryDatabaseManager.Get(connectionString) + _memoryDatabaseManager.Get(connectionString) )); return ((MemoryDbDatabaseApi)databaseApi).Database; diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs index 05c6afb7dc..ef76becbc5 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.TestApp.Application var phone = new Phone(person.Id, phoneDto.Number, phoneDto.Type); person.Phones.Add(phone); - + Repository.Update(person); return ObjectMapper.Map(phone); } @@ -43,6 +43,7 @@ namespace Volo.Abp.TestApp.Application { var person = await GetEntityByIdAsync(id); person.Phones.RemoveAll(p => p.Number == number); + Repository.Update(person); } public Task GetWithComplexType(GetWithComplexTypeInput input)