Browse Source

Register repositories without PK.

pull/194/head
Halil İbrahim Kalkan 9 years ago
parent
commit
924ba47fe5
  1. 75
      src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs
  2. 26
      src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs
  3. 6
      src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs
  4. 50
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs
  5. 9
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityNotFoundException.cs
  6. 2
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs
  7. 54
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs
  8. 37
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs
  9. 119
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
  10. 17
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs
  11. 2
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DbContextHelper.cs
  12. 8
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/EfCoreRepositoryRegistrar.cs
  13. 4
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
  14. 2
      src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerModule.cs
  15. 19
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs
  16. 89
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
  17. 5
      src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/DependencyInjection/MemoryDbRepositoryRegistrar.cs
  18. 5
      src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/MongoDbRepositoryRegistrar.cs
  19. 1
      test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj
  20. 2
      test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj.DotSettings
  21. 91
      test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs
  22. 7
      test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/PhoneInSecondDbContext.cs
  23. 10
      test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs
  24. 2
      test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
  25. 8
      test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Tests.cs

75
src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs

@ -4,66 +4,49 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Reflection;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
{ {
public static class ServiceCollectionRepositoryExtensions public static class ServiceCollectionRepositoryExtensions
{ {
public static void AddDefaultRepository(this IServiceCollection services, Type entityType, Type repositoryImplementationType) public static IServiceCollection AddDefaultRepository(this IServiceCollection services, Type entityType, Type repositoryImplementationType)
{ {
AddDefaultRepositoryForGenericPrimaryKey(services, entityType, repositoryImplementationType); //IRepository<TEntity>
var repositoryInterfaceWithoutPk = typeof(IRepository<>).MakeGenericType(entityType);
//if (BothSupportsDefaultPrimaryKey(entityType, repositoryImplementationType)) if (!repositoryInterfaceWithoutPk.IsAssignableFrom(repositoryImplementationType))
//{
// AddDefaultRepositoryForDefaultPrimaryKey(services, entityType, repositoryImplementationType);
//}
}
private static void AddDefaultRepositoryForGenericPrimaryKey(IServiceCollection services, Type entityType, Type repositoryImplementationType)
{
var primaryKeyType = EntityHelper.GetPrimaryKeyType(entityType);
//IRepository<TEntity, TPrimaryKey>
var repositoryInterface = typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType);
if (!repositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
{ {
throw new AbpException($"Given repositoryImplementationType ({repositoryImplementationType}) must implement {repositoryInterface}"); throw new AbpException($"Given repositoryImplementationType ({repositoryImplementationType}) must implement {repositoryInterfaceWithoutPk}");
} }
services.TryAddTransient(repositoryInterface, repositoryImplementationType); services.TryAddTransient(repositoryInterfaceWithoutPk, repositoryImplementationType);
//IQueryableRepository<TEntity, TPrimaryKey> //IQueryableRepository<TEntity>
var queryableRepositoryInterface = typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType); var queryableRepositoryInterfaceWithPk = typeof(IQueryableRepository<>).MakeGenericType(entityType);
if (queryableRepositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) if (repositoryInterfaceWithoutPk.IsAssignableFrom(repositoryImplementationType))
{ {
services.TryAddTransient(queryableRepositoryInterface, repositoryImplementationType); services.TryAddTransient(queryableRepositoryInterfaceWithPk, repositoryImplementationType);
} }
}
//private static void AddDefaultRepositoryForDefaultPrimaryKey(IServiceCollection services, Type entityType, Type repositoryImplementationType)
//{
// //IRepository<TEntity>
// var repositoryInterfaceWithDefaultPrimaryKey = typeof(IRepository<>).MakeGenericType(entityType);
// if (!repositoryInterfaceWithDefaultPrimaryKey.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
// {
// throw new AbpException($"Given repositoryImplementationType ({repositoryImplementationType}) must implement {repositoryInterfaceWithDefaultPrimaryKey}");
// }
// services.TryAddTransient(repositoryInterfaceWithDefaultPrimaryKey, repositoryImplementationType); var primaryKeyType = EntityHelper.FindPrimaryKeyType(entityType);
// //IQueryableRepository<TEntity> if (primaryKeyType != null)
// var queryableRepositoryInterfaceWithDefaultPrimaryKey = typeof(IQueryableRepository<>).MakeGenericType(entityType); {
// if (queryableRepositoryInterfaceWithDefaultPrimaryKey.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) //IRepository<TEntity, TPrimaryKey>
// { var repositoryInterface = typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType);
// services.TryAddTransient(queryableRepositoryInterfaceWithDefaultPrimaryKey, repositoryImplementationType); if (repositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
// } {
//} services.TryAddTransient(repositoryInterface, repositoryImplementationType);
}
//IQueryableRepository<TEntity, TPrimaryKey>
var queryableRepositoryInterface = typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType);
if (queryableRepositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
{
services.TryAddTransient(queryableRepositoryInterface, repositoryImplementationType);
}
}
//private static bool BothSupportsDefaultPrimaryKey(Type entityType, Type repositoryImplementationType) return services;
//{ }
// return typeof(IEntity<Guid>).GetTypeInfo().IsAssignableFrom(entityType) &&
// ReflectionHelper.IsAssignableToGenericType(repositoryImplementationType, typeof(IRepository<>));
//}
} }
} }

26
src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Reflection; using Volo.Abp.Reflection;
@ -20,7 +19,7 @@ namespace Volo.Abp.DependencyInjection
public Type DefaultRepositoryImplementationType { get; private set; } public Type DefaultRepositoryImplementationType { get; private set; }
//public Type DefaultRepositoryImplementationTypeWithDefaultPrimaryKey { get; private set; } public Type DefaultRepositoryImplementationTypeWithoutPrimaryKey { get; private set; }
public bool RegisterDefaultRepositories { get; private set; } public bool RegisterDefaultRepositories { get; private set; }
@ -28,7 +27,7 @@ namespace Volo.Abp.DependencyInjection
public Dictionary<Type, Type> CustomRepositories { get; } public Dictionary<Type, Type> CustomRepositories { get; }
public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null; // && DefaultRepositoryImplementationTypeWithDefaultPrimaryKey != null; public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithoutPrimaryKey != null;
protected CommonDbContextRegistrationOptions(Type originalDbContextType) protected CommonDbContextRegistrationOptions(Type originalDbContextType)
{ {
@ -80,32 +79,37 @@ namespace Volo.Abp.DependencyInjection
return this; return this;
} }
public ICommonDbContextRegistrationOptionsBuilder AddCustomRepository<TEntity, TRepository>() public ICommonDbContextRegistrationOptionsBuilder AddRepository<TEntity, TRepository>()
{ {
WithCustomRepository(typeof(TEntity), typeof(TRepository)); AddCustomRepository(typeof(TEntity), typeof(TRepository));
return this; return this;
} }
public ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType) public ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses(
Type repositoryImplementationType,
Type repositoryImplementationTypeWithoutPrimaryKey
)
{ {
Check.NotNull(repositoryImplementationType, nameof(repositoryImplementationType)); Check.NotNull(repositoryImplementationType, nameof(repositoryImplementationType));
Check.NotNull(repositoryImplementationTypeWithoutPrimaryKey, nameof(repositoryImplementationTypeWithoutPrimaryKey));
DefaultRepositoryImplementationType = repositoryImplementationType; DefaultRepositoryImplementationType = repositoryImplementationType;
DefaultRepositoryImplementationTypeWithoutPrimaryKey = repositoryImplementationTypeWithoutPrimaryKey;
return this; return this;
} }
private void WithCustomRepository(Type entityType, Type repositoryType) private void AddCustomRepository(Type entityType, Type repositoryType)
{ {
if (!ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IEntity<>))) if (!typeof(IEntity).IsAssignableFrom(entityType))
{ {
throw new AbpException($"Given entityType is not an entity: {entityType.AssemblyQualifiedName}. It must implement {typeof(IEntity<>).AssemblyQualifiedName}."); throw new AbpException($"Given entityType is not an entity: {entityType.AssemblyQualifiedName}. It must implement {typeof(IEntity<>).AssemblyQualifiedName}.");
} }
if (!ReflectionHelper.IsAssignableToGenericType(repositoryType, typeof(IRepository<,>))) if (!ReflectionHelper.IsAssignableToGenericType(repositoryType, typeof(IRepository<>)))
{ {
throw new AbpException($"Given repositoryType is not a repository: {entityType.AssemblyQualifiedName}. It must implement {typeof(IRepository<,>).AssemblyQualifiedName}."); throw new AbpException($"Given repositoryType is not a repository: {entityType.AssemblyQualifiedName}. It must implement {typeof(IRepository<>).AssemblyQualifiedName}.");
} }
CustomRepositories[entityType] = repositoryType; CustomRepositories[entityType] = repositoryType;
@ -123,7 +127,7 @@ namespace Volo.Abp.DependencyInjection
return false; return false;
} }
if (!IncludeAllEntitiesForDefaultRepositories && !ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IAggregateRoot<>))) if (!IncludeAllEntitiesForDefaultRepositories && !typeof(IAggregateRoot).IsAssignableFrom(entityType))
{ {
return false; return false;
} }

6
src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs

@ -1,4 +1,5 @@
using System; using System;
using JetBrains.Annotations;
namespace Volo.Abp.DependencyInjection namespace Volo.Abp.DependencyInjection
{ {
@ -41,14 +42,15 @@ namespace Volo.Abp.DependencyInjection
/// </summary> /// </summary>
/// <typeparam name="TEntity">Entity type</typeparam> /// <typeparam name="TEntity">Entity type</typeparam>
/// <typeparam name="TRepository">Repository type</typeparam> /// <typeparam name="TRepository">Repository type</typeparam>
ICommonDbContextRegistrationOptionsBuilder AddCustomRepository<TEntity, TRepository>(); //TODO: Rename to AddRepository! ICommonDbContextRegistrationOptionsBuilder AddRepository<TEntity, TRepository>();
/// <summary> /// <summary>
/// Uses given class(es) for default repositories. /// Uses given class(es) for default repositories.
/// </summary> /// </summary>
/// <param name="repositoryImplementationType">Repository implementation type</param> /// <param name="repositoryImplementationType">Repository implementation type</param>
/// <param name="repositoryImplementationTypeWithoutPrimaryKey">Repository implementation type (without primary key)</param>
/// <returns></returns> /// <returns></returns>
ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses(Type repositoryImplementationType); ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType, [NotNull] Type repositoryImplementationTypeWithoutPrimaryKey);
/// <summary> /// <summary>
/// Replaces given DbContext type with this DbContext type. /// Replaces given DbContext type with this DbContext type.

50
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Reflection;
namespace Volo.Abp.Domain.Entities namespace Volo.Abp.Domain.Entities
{ {
@ -13,18 +13,9 @@ namespace Volo.Abp.Domain.Entities
{ {
public static bool IsEntity([NotNull] Type type) public static bool IsEntity([NotNull] Type type)
{ {
return ReflectionHelper.IsAssignableToGenericType(type, typeof (IEntity<>)); return typeof(IEntity).IsAssignableFrom(type);
} }
/// <summary>
/// Default implementation of <see cref="Entity{TPrimaryKey}.IsTransient"/>.
///
/// This method is not used normally if given entity is derived from <see cref="Entity{TPrimaryKey}"/>.
/// Just directly call <see cref="Entity{TPrimaryKey}.IsTransient"/>.
///
/// This method is exists to help developers who want to directly implement <see cref="IEntity{TPrimaryKey}.IsTransient"/>
/// but want to use default IsTransient implementation as a shortcut.
/// </summary>
public static bool IsTransient<TPrimaryKey>(IEntity<TPrimaryKey> entity) // TODO: Completely remove IsTransient public static bool IsTransient<TPrimaryKey>(IEntity<TPrimaryKey> entity) // TODO: Completely remove IsTransient
{ {
if (EqualityComparer<TPrimaryKey>.Default.Equals(entity.Id, default)) if (EqualityComparer<TPrimaryKey>.Default.Equals(entity.Id, default))
@ -46,25 +37,50 @@ namespace Volo.Abp.Domain.Entities
return false; return false;
} }
public static Type GetPrimaryKeyType<TEntity>() /// <summary>
/// Tries to find the primary key type of the given entity type.
/// May return null if given type does not implement <see cref="IEntity{TPrimaryKey}"/>
/// </summary>
[CanBeNull]
public static Type FindPrimaryKeyType<TEntity>()
where TEntity : IEntity
{ {
return GetPrimaryKeyType(typeof (TEntity)); return FindPrimaryKeyType(typeof(TEntity));
} }
/// <summary> /// <summary>
/// Gets primary key type of given entity type /// Tries to find the primary key type of the given entity type.
/// May return null if given type does not implement <see cref="IEntity{TPrimaryKey}"/>
/// </summary> /// </summary>
public static Type GetPrimaryKeyType([NotNull] Type entityType) [CanBeNull]
public static Type FindPrimaryKeyType([NotNull] Type entityType)
{ {
if (!typeof(IEntity).IsAssignableFrom(entityType))
{
throw new AbpException($"Given {nameof(entityType)} is not an entity. It should implement {typeof(IEntity).AssemblyQualifiedName}!");
}
foreach (var interfaceType in entityType.GetTypeInfo().GetInterfaces()) foreach (var interfaceType in entityType.GetTypeInfo().GetInterfaces())
{ {
if (interfaceType.GetTypeInfo().IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof (IEntity<>)) if (interfaceType.GetTypeInfo().IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEntity<>))
{ {
return interfaceType.GenericTypeArguments[0]; return interfaceType.GenericTypeArguments[0];
} }
} }
throw new AbpException("Can not find primary key type of given entity type: " + entityType + ". Be sure that this entity type implements " + typeof(IEntity<>).AssemblyQualifiedName); return null;
}
public static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId<TEntity, TPrimaryKey>(TPrimaryKey id)
where TEntity : IEntity<TPrimaryKey>
{
var lambdaParam = Expression.Parameter(typeof(TEntity));
var lambdaBody = Expression.Equal(
Expression.PropertyOrField(lambdaParam, "Id"),
Expression.Constant(id, typeof(TPrimaryKey))
);
return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);
} }
} }
} }

9
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityNotFoundException.cs

@ -25,6 +25,15 @@ namespace Volo.Abp.Domain.Entities
} }
/// <summary>
/// Creates a new <see cref="EntityNotFoundException"/> object.
/// </summary>
public EntityNotFoundException(Type entityType)
: this(entityType, null, null)
{
}
/// <summary> /// <summary>
/// Creates a new <see cref="EntityNotFoundException"/> object. /// Creates a new <see cref="EntityNotFoundException"/> object.
/// </summary> /// </summary>

2
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs

@ -13,7 +13,7 @@
/// Defines an aggregate root with a single primary key with "Id" property. /// Defines an aggregate root with a single primary key with "Id" property.
/// </summary> /// </summary>
/// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam> /// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam>
public interface IAggregateRoot<TPrimaryKey> : IAggregateRoot, IEntity<TPrimaryKey> public interface IAggregateRoot<TPrimaryKey> : IEntity<TPrimaryKey>, IAggregateRoot
{ {
} }

54
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs

@ -14,6 +14,10 @@ namespace Volo.Abp.Domain.Repositories
public abstract class QueryableRepositoryBase<TEntity> : RepositoryBase<TEntity>, IQueryableRepository<TEntity> public abstract class QueryableRepositoryBase<TEntity> : RepositoryBase<TEntity>, IQueryableRepository<TEntity>
where TEntity : class, IEntity where TEntity : class, IEntity
{ {
public IDataFilter DataFilter { get; set; }
public ICurrentTenant CurrentTenant { get; set; }
public virtual Type ElementType => GetQueryable().ElementType; public virtual Type ElementType => GetQueryable().ElementType;
public virtual Expression Expression => GetQueryable().Expression; public virtual Expression Expression => GetQueryable().Expression;
@ -45,18 +49,31 @@ namespace Volo.Abp.Domain.Repositories
Delete(predicate); Delete(predicate);
return Task.CompletedTask; return Task.CompletedTask;
} }
//TODO: Is that needed..?
protected virtual IQueryable<TEntity> ApplyDataFilters(IQueryable<TEntity> query)
{
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
query = query.WhereIf(DataFilter.IsEnabled<ISoftDelete>(), e => ((ISoftDelete)e).IsDeleted == false);
}
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))
{
var tenantId = CurrentTenant.Id;
query = query.WhereIf(DataFilter.IsEnabled<IMultiTenant>(), e => ((IMultiTenant)e).TenantId == tenantId);
}
return query;
}
} }
public abstract class QueryableRepositoryBase<TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity>, IQueryableRepository<TEntity, TPrimaryKey> public abstract class QueryableRepositoryBase<TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity>, IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{ {
public IDataFilter DataFilter { get; set; }
public ICurrentTenant CurrentTenant { get; set; }
public virtual TEntity Find(TPrimaryKey id) public virtual TEntity Find(TPrimaryKey id)
{ {
return GetQueryable().FirstOrDefault(CreateEqualityExpressionForId(id)); return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TPrimaryKey>(id));
} }
public virtual TEntity Get(TPrimaryKey id) public virtual TEntity Get(TPrimaryKey id)
@ -97,32 +114,5 @@ namespace Volo.Abp.Domain.Repositories
Delete(id); Delete(id);
return Task.CompletedTask; return Task.CompletedTask;
} }
protected virtual IQueryable<TEntity> ApplyDataFilters(IQueryable<TEntity> query)
{
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
query = query.WhereIf(DataFilter.IsEnabled<ISoftDelete>(), e => ((ISoftDelete)e).IsDeleted == false);
}
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))
{
var tenantId = CurrentTenant.Id;
query = query.WhereIf(DataFilter.IsEnabled<IMultiTenant>(), e => ((IMultiTenant)e).TenantId == tenantId);
}
return query;
}
protected static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId(TPrimaryKey id)
{
var lambdaParam = Expression.Parameter(typeof(TEntity));
var lambdaBody = Expression.Equal(
Expression.PropertyOrField(lambdaParam, "Id"),
Expression.Constant(id, typeof(TPrimaryKey))
);
return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);
}
} }
} }

37
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Reflection;
namespace Volo.Abp.Domain.Repositories namespace Volo.Abp.Domain.Repositories
{ {
@ -45,26 +44,26 @@ namespace Volo.Abp.Domain.Repositories
protected void RegisterDefaultRepository(IServiceCollection services, Type entityType) protected void RegisterDefaultRepository(IServiceCollection services, Type entityType)
{ {
var primaryKeyType = EntityHelper.GetPrimaryKeyType(entityType); services.AddDefaultRepository(
//var isDefaultPrimaryKey = primaryKeyType == typeof(Guid); entityType,
GetDefaultRepositoryImplementationType(entityType)
);
}
Type repositoryImplementationType; private Type GetDefaultRepositoryImplementationType(Type entityType)
if (Options.SpecifiedDefaultRepositoryTypes) {
{ var primaryKeyType = EntityHelper.FindPrimaryKeyType(entityType);
repositoryImplementationType = Options.DefaultRepositoryImplementationType.MakeGenericType(entityType, primaryKeyType);
//repositoryImplementationType = isDefaultPrimaryKey if (primaryKeyType == null)
// ? Options.DefaultRepositoryImplementationTypeWithDefaultPrimaryKey.MakeGenericType(entityType)
// : Options.DefaultRepositoryImplementationType.MakeGenericType(entityType, primaryKeyType);
}
else
{ {
repositoryImplementationType = GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType, primaryKeyType); return Options.SpecifiedDefaultRepositoryTypes
//repositoryImplementationType = isDefaultPrimaryKey ? Options.DefaultRepositoryImplementationTypeWithoutPrimaryKey.MakeGenericType(entityType)
// ? GetRepositoryTypeForDefaultPk(Options.DefaultRepositoryDbContextType, entityType) : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType);
// : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType, primaryKeyType);
} }
services.AddDefaultRepository(entityType, repositoryImplementationType); return Options.SpecifiedDefaultRepositoryTypes
? Options.DefaultRepositoryImplementationType.MakeGenericType(entityType, primaryKeyType)
: GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType, primaryKeyType);
} }
public bool ShouldRegisterDefaultRepositoryFor(Type entityType) public bool ShouldRegisterDefaultRepositoryFor(Type entityType)
@ -79,7 +78,7 @@ namespace Volo.Abp.Domain.Repositories
return false; return false;
} }
if (!Options.IncludeAllEntitiesForDefaultRepositories && !ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IAggregateRoot<>))) if (!Options.IncludeAllEntitiesForDefaultRepositories && !typeof(IAggregateRoot).IsAssignableFrom(entityType))
{ {
return false; return false;
} }
@ -89,7 +88,7 @@ namespace Volo.Abp.Domain.Repositories
protected abstract IEnumerable<Type> GetEntityTypes(Type dbContextType); protected abstract IEnumerable<Type> GetEntityTypes(Type dbContextType);
//protected abstract Type GetRepositoryTypeForDefaultPk(Type dbContextType, Type entityType); protected abstract Type GetRepositoryType(Type dbContextType, Type entityType);
protected abstract Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType); protected abstract Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType);
} }

119
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

@ -7,30 +7,16 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Threading;
namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
{ {
//public class EfCoreRepository<TDbContext, TEntity> : EfCoreRepository<TDbContext, TEntity, Guid>, IEfCoreRepository<TEntity> public class EfCoreRepository<TDbContext, TEntity> : QueryableRepositoryBase<TEntity>, IEfCoreRepository<TEntity>
// where TDbContext : IEfCoreDbContext
// where TEntity : class, IEntity<Guid>
//{
// public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider)
// : base(dbContextProvider)
// {
// }
//}
public class EfCoreRepository<TDbContext, TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity, TPrimaryKey>,
IEfCoreRepository<TEntity, TPrimaryKey>,
ISupportsExplicitLoading<TEntity, TPrimaryKey>
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity
{ {
public virtual DbSet<TEntity> DbSet => DbContext.Set<TEntity>(); public virtual DbSet<TEntity> DbSet => DbContext.Set<TEntity>();
DbContext IEfCoreRepository<TEntity, TPrimaryKey>.DbContext => DbContext.As<DbContext>(); DbContext IEfCoreRepository<TEntity>.DbContext => DbContext.As<DbContext>();
protected virtual TDbContext DbContext => _dbContextProvider.GetDbContext(); protected virtual TDbContext DbContext => _dbContextProvider.GetDbContext();
@ -40,34 +26,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
{ {
_dbContextProvider = dbContextProvider; _dbContextProvider = dbContextProvider;
} }
protected override IQueryable<TEntity> GetQueryable()
{
return DbSet.AsQueryable();
}
public override async Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
var entity = await FindAsync(id, GetCancellationToken(cancellationToken));
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity;
}
public override TEntity Find(TPrimaryKey id)
{
return DbSet.Find(id);
}
public override Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
return DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken));
}
public override TEntity Insert(TEntity entity, bool autoSave = false) public override TEntity Insert(TEntity entity, bool autoSave = false)
{ {
var savedEntity = DbSet.Add(entity).Entity; var savedEntity = DbSet.Add(entity).Entity;
@ -103,6 +62,11 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
DbSet.Remove(entity); DbSet.Remove(entity);
} }
protected override IQueryable<TEntity> GetQueryable()
{
return DbSet.AsQueryable();
}
public override async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) public override async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
{ {
var entities = await GetQueryable().Where(predicate).ToListAsync(GetCancellationToken(cancellationToken)); var entities = await GetQueryable().Where(predicate).ToListAsync(GetCancellationToken(cancellationToken));
@ -130,4 +94,69 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return DbContext.Entry(entity).Reference(propertyExpression).LoadAsync(GetCancellationToken(cancellationToken)); return DbContext.Entry(entity).Reference(propertyExpression).LoadAsync(GetCancellationToken(cancellationToken));
} }
} }
public class EfCoreRepository<TDbContext, TEntity, TPrimaryKey> : EfCoreRepository<TDbContext, TEntity>,
IEfCoreRepository<TEntity, TPrimaryKey>,
ISupportsExplicitLoading<TEntity, TPrimaryKey>
where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity<TPrimaryKey>
{
public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public TEntity Get(TPrimaryKey id)
{
var entity = Find(id);
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity;
}
public virtual async Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
var entity = await FindAsync(id, GetCancellationToken(cancellationToken));
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity;
}
public virtual TEntity Find(TPrimaryKey id)
{
return DbSet.Find(id);
}
public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
return DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken));
}
public virtual void Delete(TPrimaryKey id)
{
var entity = Find(id);
if (entity == null)
{
return;
}
Delete(entity);
}
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
Delete(id);
return Task.CompletedTask;
}
}
} }

17
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs

@ -1,20 +1,19 @@
using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
{ {
//public interface IEfCoreRepository<TEntity> : IEfCoreRepository<TEntity, Guid>, IQueryableRepository<TEntity> public interface IEfCoreRepository<TEntity> : IQueryableRepository<TEntity>
// where TEntity : class, IEntity<Guid> where TEntity : class, IEntity
//{
//}
public interface IEfCoreRepository<TEntity, TPrimaryKey> : IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{ {
DbContext DbContext { get; } DbContext DbContext { get; }
DbSet<TEntity> DbSet { get; } DbSet<TEntity> DbSet { get; }
} }
public interface IEfCoreRepository<TEntity, TPrimaryKey> : IEfCoreRepository<TEntity>, IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
}
} }

2
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DbContextHelper.cs

@ -16,7 +16,7 @@ namespace Volo.Abp.EntityFrameworkCore
from property in dbContextType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance) from property in dbContextType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance)
where where
ReflectionHelper.IsAssignableToGenericType(property.PropertyType, typeof(DbSet<>)) && ReflectionHelper.IsAssignableToGenericType(property.PropertyType, typeof(DbSet<>)) &&
ReflectionHelper.IsAssignableToGenericType(property.PropertyType.GenericTypeArguments[0], typeof(IEntity<>)) typeof(IEntity).IsAssignableFrom(property.PropertyType.GenericTypeArguments[0])
select property.PropertyType.GenericTypeArguments[0]; select property.PropertyType.GenericTypeArguments[0];
} }
} }

8
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/EfCoreRepositoryRegistrar.cs

@ -17,10 +17,10 @@ namespace Volo.Abp.EntityFrameworkCore.DependencyInjection
return DbContextHelper.GetEntityTypes(dbContextType); return DbContextHelper.GetEntityTypes(dbContextType);
} }
//protected override Type GetRepositoryTypeForDefaultPk(Type dbContextType, Type entityType) protected override Type GetRepositoryType(Type dbContextType, Type entityType)
//{ {
// return typeof(EfCoreRepository<,>).MakeGenericType(dbContextType, entityType); return typeof(EfCoreRepository<,>).MakeGenericType(dbContextType, entityType);
//} }
protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType) protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType)
{ {

4
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs

@ -12,8 +12,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
services.AddAbpDbContext<IdentityDbContext>(options => services.AddAbpDbContext<IdentityDbContext>(options =>
{ {
options.AddDefaultRepositories(); options.AddDefaultRepositories();
options.AddCustomRepository<IdentityUser, EfCoreIdentityUserRepository>(); options.AddRepository<IdentityUser, EfCoreIdentityUserRepository>();
options.AddCustomRepository<IdentityRole, EfCoreIdentityRoleRepository>(); options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>();
}); });
services.AddAssemblyOf<AbpIdentityEntityFrameworkCoreModule>(); services.AddAssemblyOf<AbpIdentityEntityFrameworkCoreModule>();

2
src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerModule.cs

@ -14,7 +14,7 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
services.AddAbpDbContext<IdentityServerDbContext>(options => services.AddAbpDbContext<IdentityServerDbContext>(options =>
{ {
options.AddDefaultRepositories(); options.AddDefaultRepositories();
options.AddCustomRepository<Client, ClientRepository>(); options.AddRepository<Client, ClientRepository>();
}); });
services.AddAssemblyOf<AbpIdentityServerEntityFrameworkCoreModule>(); services.AddAssemblyOf<AbpIdentityServerEntityFrameworkCoreModule>();

19
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs

@ -1,20 +1,19 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories.MemoryDb namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
//public interface IMemoryDbRepository<TEntity> : IMemoryDbRepository<TEntity, Guid>, IQueryableRepository<TEntity> public interface IMemoryDbRepository<TEntity> : IQueryableRepository<TEntity>
// where TEntity : class, IEntity<Guid> where TEntity : class, IEntity
//{
//}
public interface IMemoryDbRepository<TEntity, TPrimaryKey> : IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{ {
IMemoryDatabase Database { get; } IMemoryDatabase Database { get; }
List<TEntity> Collection { get; } List<TEntity> Collection { get; }
} }
public interface IMemoryDbRepository<TEntity, TPrimaryKey> : IMemoryDbRepository<TEntity>, IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
}
} }

89
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs

@ -1,24 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.MemoryDb; using Volo.Abp.MemoryDb;
namespace Volo.Abp.Domain.Repositories.MemoryDb namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
//public class MemoryDbRepository<TMemoryDbContext, TEntity> : MemoryDbRepository<TMemoryDbContext, TEntity, Guid>, IMemoryDbRepository<TEntity> public class MemoryDbRepository<TMemoryDbContext, TEntity> : QueryableRepositoryBase<TEntity>, IMemoryDbRepository<TEntity>
// where TMemoryDbContext : MemoryDbContext
// where TEntity : class, IEntity<Guid>
//{
// public MemoryDbRepository(IMemoryDatabaseProvider<TMemoryDbContext> databaseProvider)
// : base(databaseProvider)
// {
// }
//}
public class MemoryDbRepository<TMemoryDbContext, TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity, TPrimaryKey>, IMemoryDbRepository<TEntity, TPrimaryKey>
where TMemoryDbContext : MemoryDbContext where TMemoryDbContext : MemoryDbContext
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity
{ {
public virtual List<TEntity> Collection => Database.Collection<TEntity>(); public virtual List<TEntity> Collection => Database.Collection<TEntity>();
@ -33,11 +25,41 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
public override TEntity Insert(TEntity entity, bool autoSave = false) public override TEntity Insert(TEntity entity, bool autoSave = false)
{ {
SetIdIfNeeded(entity);
Collection.Add(entity); Collection.Add(entity);
return entity; return entity;
} }
public override TEntity Update(TEntity entity)
{
return entity;
}
public override void Delete(TEntity entity)
{
Collection.Remove(entity);
}
protected override IQueryable<TEntity> GetQueryable()
{
return ApplyDataFilters(Collection.AsQueryable());
}
}
public class MemoryDbRepository<TMemoryDbContext, TEntity, TPrimaryKey> : MemoryDbRepository<TMemoryDbContext, TEntity>, IMemoryDbRepository<TEntity, TPrimaryKey>
where TMemoryDbContext : MemoryDbContext
where TEntity : class, IEntity<TPrimaryKey>
{
public MemoryDbRepository(IMemoryDatabaseProvider<TMemoryDbContext> databaseProvider)
: base(databaseProvider)
{
}
public override TEntity Insert(TEntity entity, bool autoSave = false)
{
SetIdIfNeeded(entity);
return base.Insert(entity, autoSave);
}
private void SetIdIfNeeded(TEntity entity) private void SetIdIfNeeded(TEntity entity)
{ {
if (typeof(TPrimaryKey) == typeof(int) || typeof(TPrimaryKey) == typeof(long) || typeof(TPrimaryKey) == typeof(Guid)) if (typeof(TPrimaryKey) == typeof(int) || typeof(TPrimaryKey) == typeof(long) || typeof(TPrimaryKey) == typeof(Guid))
@ -49,19 +71,48 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
} }
} }
public override TEntity Update(TEntity entity) public virtual TEntity Find(TPrimaryKey id)
{ {
return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TPrimaryKey>(id));
}
public virtual TEntity Get(TPrimaryKey id)
{
var entity = Find(id);
if (entity == null)
{
throw new EntityNotFoundException(typeof(TEntity), id);
}
return entity; return entity;
} }
public override void Delete(TEntity entity) public virtual Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{ {
Collection.Remove(entity); return Task.FromResult(Get(id));
} }
protected override IQueryable<TEntity> GetQueryable() public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{ {
return ApplyDataFilters(Collection.AsQueryable()); return Task.FromResult(Find(id));
}
public virtual void Delete(TPrimaryKey id)
{
var entity = Find(id);
if (entity == null)
{
return;
}
Delete(entity);
}
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
Delete(id);
return Task.CompletedTask;
} }
} }
} }

5
src/Volo.Abp.MemoryDb/Volo/Abp/MemoryDb/DependencyInjection/MemoryDbRepositoryRegistrar.cs

@ -18,6 +18,11 @@ namespace Volo.Abp.MemoryDb.DependencyInjection
return memoryDbContext.GetEntityTypes(); return memoryDbContext.GetEntityTypes();
} }
protected override Type GetRepositoryType(Type dbContextType, Type entityType)
{
return typeof(MemoryDbRepository<,>).MakeGenericType(dbContextType, entityType);
}
protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType) protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType)
{ {
return typeof(MemoryDbRepository<,,>).MakeGenericType(dbContextType, entityType, primaryKeyType); return typeof(MemoryDbRepository<,,>).MakeGenericType(dbContextType, entityType, primaryKeyType);

5
src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/MongoDbRepositoryRegistrar.cs

@ -19,6 +19,11 @@ namespace Volo.Abp.MongoDB.DependencyInjection
return mongoDbContext.GetMappings().Select(m => m.EntityType); return mongoDbContext.GetMappings().Select(m => m.EntityType);
} }
protected override Type GetRepositoryType(Type dbContextType, Type entityType)
{
throw new NotImplementedException();
}
protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType) protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType)
{ {
return typeof(MongoDbRepository<,,>).MakeGenericType(dbContextType, entityType, primaryKeyType); return typeof(MongoDbRepository<,,>).MakeGenericType(dbContextType, entityType, primaryKeyType);

1
test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<AssemblyName>Volo.Abp.Ddd.Tests</AssemblyName> <AssemblyName>Volo.Abp.Ddd.Tests</AssemblyName>
<PackageId>Volo.Abp.Ddd.Tests</PackageId> <PackageId>Volo.Abp.Ddd.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>

2
test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

91
test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
@ -25,8 +27,10 @@ namespace Volo.Abp.Domain.Repositories
//Assert //Assert
//services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithDefaultPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithDefaultPk>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithoutPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithoutPk>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldNotContainService(typeof(IRepository<MyTestEntityWithInt32Pk, int>)); services.ShouldNotContainService(typeof(IRepository<MyTestEntityWithInt32Pk, int>));
} }
@ -46,8 +50,10 @@ namespace Volo.Abp.Domain.Repositories
//Assert //Assert
//services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithDefaultPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithDefaultPk>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithoutPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithoutPk>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk>), typeof(MyTestDefaultRepository<MyTestEntityWithInt32Pk, int>));
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestDefaultRepository<MyTestEntityWithInt32Pk, int>)); services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestDefaultRepository<MyTestEntityWithInt32Pk, int>));
} }
@ -61,7 +67,7 @@ namespace Volo.Abp.Domain.Repositories
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext)); var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext));
options options
.AddDefaultRepositories(true) .AddDefaultRepositories(true)
.AddCustomRepository<MyTestAggregateRootWithGuidPk, MyTestAggregateRootWithDefaultPkCustomRepository>(); .AddRepository<MyTestAggregateRootWithGuidPk, MyTestAggregateRootWithDefaultPkCustomRepository>();
//Act //Act
@ -69,7 +75,8 @@ namespace Volo.Abp.Domain.Repositories
//Assert //Assert
//services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithDefaultPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithoutPk>), typeof(MyTestDefaultRepository<MyTestAggregateRootWithoutPk>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestAggregateRootWithDefaultPkCustomRepository));
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestDefaultRepository<MyTestEntityWithInt32Pk, int>)); services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestDefaultRepository<MyTestEntityWithInt32Pk, int>));
} }
@ -84,7 +91,7 @@ namespace Volo.Abp.Domain.Repositories
var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext)); var options = new TestDbContextRegistrationOptions(typeof(MyFakeDbContext));
options options
.AddDefaultRepositories(true) .AddDefaultRepositories(true)
.SetDefaultRepositoryClasses(typeof(MyTestCustomBaseRepository<,>)); .SetDefaultRepositoryClasses(typeof(MyTestCustomBaseRepository<,>), typeof(MyTestCustomBaseRepository<>));
//Act //Act
@ -92,14 +99,15 @@ namespace Volo.Abp.Domain.Repositories
//Assert //Assert
//services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithDefaultPk>), typeof(MyTestCustomBaseRepository<MyTestAggregateRootWithDefaultPk>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithoutPk>), typeof(MyTestCustomBaseRepository<MyTestAggregateRootWithoutPk>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk>), typeof(MyTestCustomBaseRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestCustomBaseRepository<MyTestAggregateRootWithGuidPk, Guid>)); services.ShouldContainTransient(typeof(IRepository<MyTestAggregateRootWithGuidPk, Guid>), typeof(MyTestCustomBaseRepository<MyTestAggregateRootWithGuidPk, Guid>));
services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestCustomBaseRepository<MyTestEntityWithInt32Pk, int>)); services.ShouldContainTransient(typeof(IRepository<MyTestEntityWithInt32Pk, int>), typeof(MyTestCustomBaseRepository<MyTestEntityWithInt32Pk, int>));
} }
public class MyTestRepositoryRegistrar : RepositoryRegistrarBase<CommonDbContextRegistrationOptions> public class MyTestRepositoryRegistrar : RepositoryRegistrarBase<CommonDbContextRegistrationOptions>
{ {
public MyTestRepositoryRegistrar(CommonDbContextRegistrationOptions options) public MyTestRepositoryRegistrar(CommonDbContextRegistrationOptions options)
: base(options) : base(options)
{ {
} }
@ -109,14 +117,15 @@ namespace Volo.Abp.Domain.Repositories
return new[] return new[]
{ {
typeof(MyTestEntityWithInt32Pk), typeof(MyTestEntityWithInt32Pk),
typeof(MyTestAggregateRootWithGuidPk) typeof(MyTestAggregateRootWithGuidPk),
typeof(MyTestAggregateRootWithoutPk)
}; };
} }
//protected override Type GetRepositoryTypeForDefaultPk(Type dbContextType, Type entityType) protected override Type GetRepositoryType(Type dbContextType, Type entityType)
//{ {
// return typeof(MyTestDefaultRepository<>).MakeGenericType(entityType); return typeof(MyTestDefaultRepository<>).MakeGenericType(entityType);
//} }
protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType) protected override Type GetRepositoryType(Type dbContextType, Type entityType, Type primaryKeyType)
{ {
@ -128,7 +137,7 @@ namespace Volo.Abp.Domain.Repositories
public class MyTestAggregateRootWithGuidPk : AggregateRoot<Guid> public class MyTestAggregateRootWithGuidPk : AggregateRoot<Guid>
{ {
} }
public class MyTestEntityWithInt32Pk : Entity<int> public class MyTestEntityWithInt32Pk : Entity<int>
@ -136,31 +145,59 @@ namespace Volo.Abp.Domain.Repositories
} }
//public class MyTestDefaultRepository<TEntity> : MyTestDefaultRepository<TEntity, Guid> public class MyTestAggregateRootWithoutPk : AggregateRoot
// where TEntity : class, IEntity<Guid> {
//{ public string MyId { get; set; }
}
//}
public class MyTestDefaultRepository<TEntity> : RepositoryBase<TEntity>
where TEntity : class, IEntity
{
public override TEntity Insert(TEntity entity, bool autoSave = false)
{
throw new NotImplementedException();
}
public override TEntity Update(TEntity entity)
{
throw new NotImplementedException();
}
public override void Delete(TEntity entity)
{
throw new NotImplementedException();
}
}
public class MyTestDefaultRepository<TEntity, TPrimaryKey> : RepositoryBase<TEntity, TPrimaryKey> public class MyTestDefaultRepository<TEntity, TPrimaryKey> : MyTestDefaultRepository<TEntity>, IRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{ {
public override TEntity Find(TPrimaryKey id) public TEntity Get(TPrimaryKey id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override TEntity Insert(TEntity entity, bool autoSave = false) public Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override TEntity Update(TEntity entity) public TEntity Find(TPrimaryKey id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void Delete(TEntity entity) public Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public void Delete(TPrimaryKey id)
{
throw new NotImplementedException();
}
public Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -171,6 +208,12 @@ namespace Volo.Abp.Domain.Repositories
} }
public class MyTestCustomBaseRepository<TEntity> : MyTestDefaultRepository<TEntity>
where TEntity : class, IEntity
{
}
public class MyTestCustomBaseRepository<TEntity, TPrimaryKey> : MyTestDefaultRepository<TEntity, TPrimaryKey> public class MyTestCustomBaseRepository<TEntity, TPrimaryKey> : MyTestDefaultRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{ {
@ -179,7 +222,7 @@ namespace Volo.Abp.Domain.Repositories
public class TestDbContextRegistrationOptions : CommonDbContextRegistrationOptions public class TestDbContextRegistrationOptions : CommonDbContextRegistrationOptions
{ {
public TestDbContextRegistrationOptions(Type originalDbContextType) public TestDbContextRegistrationOptions(Type originalDbContextType)
: base(originalDbContextType) : base(originalDbContextType)
{ {
} }

7
test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/PhoneInSecondDbContext.cs

@ -1,11 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema; using System;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
{ {
[Table("AppPhones")] [Table("AppPhones")]
public class PhoneInSecondDbContext : AggregateRoot<long> public class PhoneInSecondDbContext : AggregateRoot
{ {
public virtual Guid PersonId { get; set; }
public virtual string Number { get; set; } public virtual string Number { get; set; }
} }
} }

10
test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondDbContext.cs

@ -12,5 +12,15 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
: base(options) : base(options)
{ {
} }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<PhoneInSecondDbContext>(b =>
{
b.HasKey(p => new { p.PersonId, p.Number });
});
}
} }
} }

2
test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs

@ -22,7 +22,7 @@ namespace Volo.Abp.EntityFrameworkCore
services.AddAbpDbContext<TestAppDbContext>(options => services.AddAbpDbContext<TestAppDbContext>(options =>
{ {
options.AddDefaultRepositories(); options.AddDefaultRepositories(true);
options.ReplaceDbContext<IThirdDbContext>(); options.ReplaceDbContext<IThirdDbContext>();
}); });

8
test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Basic_Repository_Tests.cs → test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Tests.cs

@ -10,17 +10,17 @@ using Xunit;
namespace Volo.Abp.EntityFrameworkCore.Repositories namespace Volo.Abp.EntityFrameworkCore.Repositories
{ {
public class Basic_Repository_Tests : EntityFrameworkCoreTestBase public class Repository_Tests : EntityFrameworkCoreTestBase
{ {
private readonly IQueryableRepository<Person, Guid> _personRepository; private readonly IQueryableRepository<Person, Guid> _personRepository;
private readonly IQueryableRepository<BookInSecondDbContext, Guid> _bookRepository; private readonly IQueryableRepository<BookInSecondDbContext, Guid> _bookRepository;
private readonly IQueryableRepository<PhoneInSecondDbContext, long> _phoneInSecondDbContextRepository; private readonly IQueryableRepository<PhoneInSecondDbContext> _phoneInSecondDbContextRepository;
public Basic_Repository_Tests() public Repository_Tests()
{ {
_personRepository = ServiceProvider.GetRequiredService<IQueryableRepository<Person, Guid>>(); _personRepository = ServiceProvider.GetRequiredService<IQueryableRepository<Person, Guid>>();
_bookRepository = ServiceProvider.GetRequiredService<IQueryableRepository<BookInSecondDbContext, Guid>>(); _bookRepository = ServiceProvider.GetRequiredService<IQueryableRepository<BookInSecondDbContext, Guid>>();
_phoneInSecondDbContextRepository = ServiceProvider.GetRequiredService<IQueryableRepository<PhoneInSecondDbContext, long>>(); _phoneInSecondDbContextRepository = ServiceProvider.GetRequiredService<IQueryableRepository<PhoneInSecondDbContext>>();
} }
[Fact] [Fact]
Loading…
Cancel
Save