Browse Source

Merge pull request #1151 from abpframework/maliming/memorydb

resolve #1147 Use serialization/deserialization for memorydb.
pull/1159/head
Halil İbrahim Kalkan 7 years ago
committed by GitHub
parent
commit
f65058f2cc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs
  2. 13
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabaseCollection.cs
  3. 2
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs
  4. 11
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbSerializer.cs
  5. 19
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs
  6. 56
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseCollection.cs
  7. 20
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabaseManager.cs
  8. 5
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
  9. 27
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs
  10. 2
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs
  11. 6
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs
  12. 7
      framework/src/Volo.Abp.MemoryDb/Volo/Abp/Uow/MemoryDb/UnitOfWorkMemoryDatabaseProvider.cs
  13. 3
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs

4
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 namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
public interface IMemoryDatabase public interface IMemoryDatabase
{ {
List<TEntity> Collection<TEntity>(); IMemoryDatabaseCollection<TEntity> Collection<TEntity>() where TEntity : class, IEntity;
TKey GenerateNextId<TEntity, TKey>(); TKey GenerateNextId<TEntity, TKey>();
} }

13
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<TEntity> : IEnumerable<TEntity>
{
void Add(TEntity entity);
void Update(TEntity entity);
void Remove(TEntity entity);
}
}

2
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; } IMemoryDatabase Database { get; }
List<TEntity> Collection { get; } IMemoryDatabaseCollection<TEntity> Collection { get; }
} }
public interface IMemoryDbRepository<TEntity, TKey> : IMemoryDbRepository<TEntity>, IRepository<TEntity, TKey> public interface IMemoryDbRepository<TEntity, TKey> : IMemoryDbRepository<TEntity>, IRepository<TEntity, TKey>

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

19
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.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories.MemoryDb namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
public class MemoryDatabase : IMemoryDatabase public class MemoryDatabase : IMemoryDatabase, ITransientDependency
{ {
private readonly ConcurrentDictionary<Type, object> _sets; private readonly ConcurrentDictionary<Type, object> _sets;
private readonly ConcurrentDictionary<Type, InMemoryIdGenerator> _entityIdGenerators; private readonly ConcurrentDictionary<Type, InMemoryIdGenerator> _entityIdGenerators;
public MemoryDatabase() private readonly IServiceProvider _serviceProvider;
public MemoryDatabase(IServiceProvider serviceProvider)
{ {
_serviceProvider = serviceProvider;
_sets = new ConcurrentDictionary<Type, object>(); _sets = new ConcurrentDictionary<Type, object>();
_entityIdGenerators = new ConcurrentDictionary<Type, InMemoryIdGenerator>(); _entityIdGenerators = new ConcurrentDictionary<Type, InMemoryIdGenerator>();
} }
public List<TEntity> Collection<TEntity>() public IMemoryDatabaseCollection<TEntity> Collection<TEntity>()
where TEntity : class, IEntity
{ {
return _sets.GetOrAdd(typeof(TEntity), _ => new List<TEntity>()) as List<TEntity>; return _sets.GetOrAdd(typeof(TEntity),
_ => _serviceProvider.GetRequiredService<IMemoryDatabaseCollection<TEntity>>()) as
IMemoryDatabaseCollection<TEntity>;
} }
public TKey GenerateNextId<TEntity, TKey>() public TKey GenerateNextId<TEntity, TKey>()

56
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<TEntity> : IMemoryDatabaseCollection<TEntity>
where TEntity : class, IEntity
{
private readonly Dictionary<string, byte[]> _dictionary = new Dictionary<string, byte[]>();
private readonly IMemoryDbSerializer _memoryDbSerializer;
public MemoryDatabaseCollection(IMemoryDbSerializer memoryDbSerializer)
{
_memoryDbSerializer = memoryDbSerializer;
}
public IEnumerator<TEntity> GetEnumerator()
{
foreach (var entity in _dictionary.Values)
{
yield return _memoryDbSerializer.Deserialize(entity, typeof(TEntity)).As<TEntity>();
}
}
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(",");
}
}
}

20
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 namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
public static class MemoryDatabaseManager public class MemoryDatabaseManager : ISingletonDependency
{ {
private static ConcurrentDictionary<string, IMemoryDatabase> _databases; private readonly ConcurrentDictionary<string, IMemoryDatabase> _databases =
new ConcurrentDictionary<string, IMemoryDatabase>();
static MemoryDatabaseManager() private readonly IServiceProvider _serviceProvider;
public MemoryDatabaseManager(IServiceProvider serviceProvider)
{ {
_databases = new ConcurrentDictionary<string, IMemoryDatabase>(); _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<IMemoryDatabase>());
} }
} }
} }

5
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! //TODO: Add dbcontext just like mongodb implementation!
public virtual List<TEntity> Collection => Database.Collection<TEntity>(); public virtual IMemoryDatabaseCollection<TEntity> Collection => Database.Collection<TEntity>();
public virtual IMemoryDatabase Database => DatabaseProvider.GetDatabase(); 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) public override TEntity Update(TEntity entity, bool autoSave = false)
{ {
Collection.Update(entity);
return entity; return entity;
} }
@ -48,7 +49,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
public override long GetCount() public override long GetCount()
{ {
return Collection.Count; return Collection.Count();
} }
protected override IQueryable<TEntity> GetQueryable() protected override IQueryable<TEntity> GetQueryable()

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

2
framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs

@ -13,7 +13,7 @@ namespace Volo.Abp.Domain.Repositories
return repository.ToMemoryDbRepository().Database; return repository.ToMemoryDbRepository().Database;
} }
public static List<TEntity> GetCollection<TEntity, TKey>(this IBasicRepository<TEntity, TKey> repository) public static IMemoryDatabaseCollection<TEntity> GetCollection<TEntity, TKey>(this IBasicRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMemoryDbRepository().Collection; return repository.ToMemoryDbRepository().Collection;

6
framework/src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/AbpMemoryDbModule.cs

@ -1,19 +1,19 @@
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.Domain.Repositories.MemoryDb;
using Volo.Abp.Json;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Uow.MemoryDb; using Volo.Abp.Uow.MemoryDb;
namespace Volo.Abp.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))] [DependsOn(typeof(AbpDddDomainModule))]
public class AbpMemoryDbModule : AbpModule public class AbpMemoryDbModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.TryAddTransient(typeof(IMemoryDatabaseProvider<>), typeof(UnitOfWorkMemoryDatabaseProvider<>)); context.Services.TryAddTransient(typeof(IMemoryDatabaseProvider<>), typeof(UnitOfWorkMemoryDatabaseProvider<>));
context.Services.TryAddTransient(typeof(IMemoryDatabaseCollection<>), typeof(MemoryDatabaseCollection<>));
} }
} }
} }

7
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 IUnitOfWorkManager _unitOfWorkManager;
private readonly IConnectionStringResolver _connectionStringResolver; private readonly IConnectionStringResolver _connectionStringResolver;
private readonly MemoryDatabaseManager _memoryDatabaseManager;
public UnitOfWorkMemoryDatabaseProvider( public UnitOfWorkMemoryDatabaseProvider(
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IConnectionStringResolver connectionStringResolver, IConnectionStringResolver connectionStringResolver,
TMemoryDbContext dbContext) TMemoryDbContext dbContext,
MemoryDatabaseManager memoryDatabaseManager)
{ {
_unitOfWorkManager = unitOfWorkManager; _unitOfWorkManager = unitOfWorkManager;
_connectionStringResolver = connectionStringResolver; _connectionStringResolver = connectionStringResolver;
DbContext = dbContext; DbContext = dbContext;
_memoryDatabaseManager = memoryDatabaseManager;
} }
public IMemoryDatabase GetDatabase() public IMemoryDatabase GetDatabase()
@ -36,7 +39,7 @@ namespace Volo.Abp.Uow.MemoryDb
var databaseApi = unitOfWork.GetOrAddDatabaseApi( var databaseApi = unitOfWork.GetOrAddDatabaseApi(
dbContextKey, dbContextKey,
() => new MemoryDbDatabaseApi( () => new MemoryDbDatabaseApi(
MemoryDatabaseManager.Get(connectionString) _memoryDatabaseManager.Get(connectionString)
)); ));
return ((MemoryDbDatabaseApi)databaseApi).Database; return ((MemoryDbDatabaseApi)databaseApi).Database;

3
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); var phone = new Phone(person.Id, phoneDto.Number, phoneDto.Type);
person.Phones.Add(phone); person.Phones.Add(phone);
Repository.Update(person);
return ObjectMapper.Map<Phone, PhoneDto>(phone); return ObjectMapper.Map<Phone, PhoneDto>(phone);
} }
@ -43,6 +43,7 @@ namespace Volo.Abp.TestApp.Application
{ {
var person = await GetEntityByIdAsync(id); var person = await GetEntityByIdAsync(id);
person.Phones.RemoveAll(p => p.Number == number); person.Phones.RemoveAll(p => p.Number == number);
Repository.Update(person);
} }
public Task<GetWithComplexTypeInput> GetWithComplexType(GetWithComplexTypeInput input) public Task<GetWithComplexTypeInput> GetWithComplexType(GetWithComplexTypeInput input)

Loading…
Cancel
Save