Merge pull request #1151 from abpframework/maliming/memorydb

resolve #1147 Use serialization/deserialization for memorydb.
pull/1159/head
Halil İbrahim Kalkan 6 years ago committed by GitHub
commit f65058f2cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,10 +1,10 @@
using System.Collections.Generic;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories.MemoryDb
{
public interface IMemoryDatabase
{
List<TEntity> Collection<TEntity>();
IMemoryDatabaseCollection<TEntity> Collection<TEntity>() where TEntity : class, IEntity;
TKey GenerateNextId<TEntity, TKey>();
}

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

@ -8,7 +8,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
{
IMemoryDatabase Database { get; }
List<TEntity> Collection { get; }
IMemoryDatabaseCollection<TEntity> Collection { get; }
}
public interface IMemoryDbRepository<TEntity, TKey> : IMemoryDbRepository<TEntity>, IRepository<TEntity, TKey>

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

@ -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<Type, object> _sets;
private readonly ConcurrentDictionary<Type, InMemoryIdGenerator> _entityIdGenerators;
public MemoryDatabase()
private readonly IServiceProvider _serviceProvider;
public MemoryDatabase(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_sets = new ConcurrentDictionary<Type, object>();
_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>()

@ -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(",");
}
}
}

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

@ -14,7 +14,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
{
//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();
@ -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<TEntity> GetQueryable()

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

@ -13,7 +13,7 @@ namespace Volo.Abp.Domain.Repositories
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>
{
return repository.ToMemoryDbRepository().Collection;

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

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

@ -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, PhoneDto>(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<GetWithComplexTypeInput> GetWithComplexType(GetWithComplexTypeInput input)

Loading…
Cancel
Save