Browse Source

Renamed TPrimaryKey to TKey and documented entities.

pull/194/head
Halil İbrahim Kalkan 9 years ago
parent
commit
76fb510c3d
  1. 153
      docs/Entities.md
  2. 4
      src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs
  3. 10
      src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs
  4. 4
      src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs
  5. 52
      src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs
  6. 52
      src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs
  7. 12
      src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppServiceBase.cs
  8. 28
      src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs
  9. 28
      src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs
  10. 10
      src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs
  11. 4
      src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs
  12. 4
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs
  13. 14
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs
  14. 18
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs
  15. 6
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs
  16. 8
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs
  17. 4
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs
  18. 16
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IRepository.cs
  19. 4
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs
  20. 18
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs
  21. 16
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs
  22. 28
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs
  23. 2
      src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs
  24. 16
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs
  25. 20
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
  26. 4
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs
  27. 2
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs
  28. 4
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs
  29. 16
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/InMemoryIdGenerator.cs
  30. 4
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs
  31. 22
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
  32. 16
      src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs
  33. 4
      src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs
  34. 18
      src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
  35. 20
      src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs
  36. 20
      test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs
  37. 72
      test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs

153
docs/Entities.md

@ -0,0 +1,153 @@
## Entities
Entities are one of the core concepts of DDD (Domain Driven Design). Eric Evans describe it as "*An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identity*".
An entity is generally mapped to a table in a relational database.
### Entity Class
Entities are derived from `Entity<TKey>` class as shown below:
```C#
public class Person : Entity<int>
{
public string Name { get; set; }
public DateTime CreationTime { get; set; }
public Person()
{
CreationTime = DateTime.Now;
}
}
```
> If you do not want derive your entity from the base `Entity<TKey>` class, you can directly implement `IEntity<TKey>` interface.
`Entity<TKey>` class just defines an `Id` property with the given primary **key type**, which is `int` in the sample above. It can be other types like `string`, `Guid`, `long` or whatever you need.
Entity class also overrides the **equality** operator (==) to easily check if two entities are equal (they are equals if they are same entity type and their Ids are equals).
#### Entities with Composite Keys
Some entities may need to have **composite keys**. In that case, you can derive your entity from the non-generic `Entity` class. Example:
````C#
public class UserRole : Entity
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public DateTime CreationTime { get; set; }
public Phone()
{
}
}
````
For the example above, the composite key is composed of `UserId` and `RoleId`. For a relational database, it is the composite primary key of the related table.
> Composite primary keys has some restriction with repositories. Since it has not known Id property, you can not use `IRepository<TEntity, TKey>` for these entities. However, you can always use `IRepository<TEntity>`. See repository documentation (TODO: link) for more.
### AggregateRoot Class
"*Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items, these will be separate objects, but it's useful to treat the order (together with its line items) as a single aggregate.*" (see the [full description](http://martinfowler.com/bliki/DDD_Aggregate.html))
`AggregateRoot` extends `Entity`. So, it also has an `Id` property by default.
> Notice that ABP creates default repositories only for aggregate roots by default. However, it's possible to include all entities. See repository documentation (TODO: link) for more.
ABP does not force you to use aggregate roots, you can only use the `Entity` class as defined before. However, if you want to implement DDD and want to create aggregate root classes, there are some best practices you can consider:
* An aggregate root is responsible to preserve it's own integrity. This is also true for all entities, but aggregate root has responsibility for it's sub entities too.
* An aggregate root can be referenced by it's Id. Do not reference it by navigation property.
* An aggregate root is treated as a single unit. It's retrieved and updated as a single unit. It's generally considered as a transaction boundary.
* Work with sub-entities over the aggregate root, do not modify them independently.
#### Aggregate Example
This is a full sample of an aggregate root with a related sub-entity collection:
````C#
public class Order : AggregateRoot<Guid>
{
public virtual string ReferenceNo { get; protected set; }
public virtual int TotalItemCount { get; protected set; }
public virtual DateTime CreationTime { get; protected set; }
public virtual List<OrderLine> OrderLines { get; protected set; }
protected Order()
{
}
public Order(Guid id, string referenceNo)
{
Id = id;
ReferenceNo = referenceNo;
OrderLines = new List<OrderLine>();
}
public void AddProduct(Guid productId, int count)
{
if (count <= 0)
{
throw new ArgumentException(
"You can not add zero or negative count of products!",
nameof(count)
);
}
var existingLine = OrderLines.FirstOrDefault(ol => ol.ProductId == productId);
if (existingLine == null)
{
OrderLines.Add(new OrderLine(this.Id, productId, count));
}
else
{
existingLine.ChangeCount(existingLine.Count + count);
}
TotalItemCount += count;
}
}
public class OrderLine : Entity
{
public virtual Guid OrderId { get; protected set; }
public virtual Guid ProductId { get; protected set; }
public virtual int Count { get; protected set; }
protected OrderLine()
{
}
internal OrderLine(Guid orderId, Guid productId, int count)
{
OrderId = orderId;
ProductId = productId;
Count = count;
}
internal void ChangeCount(int newCount)
{
Count = newCount;
}
}
````
In this example;
* `Order` is an **aggregate root entity** with `Guid` type `Id` property. It has a collection of `OrderLine` entities. `OrderLine` is another entity with a composite primary key (`OrderLine` and ` ProductId`).
* ...

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

@ -31,14 +31,14 @@ namespace Microsoft.Extensions.DependencyInjection
if (primaryKeyType != null) if (primaryKeyType != null)
{ {
//IRepository<TEntity, TPrimaryKey> //IRepository<TEntity, TKey>
var repositoryInterface = typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType); var repositoryInterface = typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType);
if (repositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) if (repositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
{ {
services.TryAddTransient(repositoryInterface, repositoryImplementationType); services.TryAddTransient(repositoryInterface, repositoryImplementationType);
} }
//IQueryableRepository<TEntity, TPrimaryKey> //IQueryableRepository<TEntity, TKey>
var queryableRepositoryInterface = typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType); var queryableRepositoryInterface = typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType);
if (queryableRepositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) if (queryableRepositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType))
{ {

10
src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs

@ -8,15 +8,15 @@ namespace Volo.Abp.Application.Dtos
} }
} }
public class EntityDto<TPrimaryKey> : EntityDto, IEntityDto<TPrimaryKey> public class EntityDto<TKey> : EntityDto, IEntityDto<TKey>
{ {
/// <summary> /// <summary>
/// Id of the entity. /// Id of the entity.
/// </summary> /// </summary>
public TPrimaryKey Id { get; set; } public TKey Id { get; set; }
/// <summary> /// <summary>
/// Creates a new <see cref="EntityDto{TPrimaryKey}"/> object. /// Creates a new <see cref="EntityDto{TKey}"/> object.
/// </summary> /// </summary>
public EntityDto() public EntityDto()
{ {
@ -24,10 +24,10 @@ namespace Volo.Abp.Application.Dtos
} }
/// <summary> /// <summary>
/// Creates a new <see cref="EntityDto{TPrimaryKey}"/> object. /// Creates a new <see cref="EntityDto{TKey}"/> object.
/// </summary> /// </summary>
/// <param name="id">Id of the entity</param> /// <param name="id">Id of the entity</param>
public EntityDto(TPrimaryKey id) public EntityDto(TKey id)
{ {
Id = id; Id = id;
} }

4
src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs

@ -5,8 +5,8 @@
} }
public interface IEntityDto<TPrimaryKey> : IEntityDto public interface IEntityDto<TKey> : IEntityDto
{ {
TPrimaryKey Id { get; set; } TKey Id { get; set; }
} }
} }

52
src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs

@ -7,59 +7,59 @@ using Volo.Abp.Linq;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public abstract class AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey> public abstract class AsyncCrudAppService<TEntity, TEntityDto, TKey>
: AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, PagedAndSortedResultRequestDto> : AsyncCrudAppService<TEntity, TEntityDto, TKey, PagedAndSortedResultRequestDto>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected AsyncCrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected AsyncCrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput> public abstract class AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput>
: AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TEntityDto, TEntityDto> : AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TEntityDto, TEntityDto>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected AsyncCrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected AsyncCrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput> public abstract class AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput>
: AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TCreateInput> : AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TCreateInput>
where TGetAllInput : IPagedAndSortedResultRequest where TGetAllInput : IPagedAndSortedResultRequest
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
where TCreateInput : IEntityDto<TPrimaryKey> where TCreateInput : IEntityDto<TKey>
{ {
protected AsyncCrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected AsyncCrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class AsyncCrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput> public abstract class AsyncCrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>
: CrudAppServiceBase<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput>, : CrudAppServiceBase<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>,
IAsyncCrudAppService<TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput> IAsyncCrudAppService<TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; }
protected AsyncCrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected AsyncCrudAppService(IQueryableRepository<TEntity, TKey> repository)
:base(repository) :base(repository)
{ {
AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance; AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance;
} }
public virtual async Task<TEntityDto> GetAsync(TPrimaryKey id) public virtual async Task<TEntityDto> GetAsync(TKey id)
{ {
CheckGetPermission(); CheckGetPermission();
@ -98,7 +98,7 @@ namespace Volo.Abp.Application.Services
return MapToEntityDto(entity); return MapToEntityDto(entity);
} }
public virtual async Task<TEntityDto> UpdateAsync(TPrimaryKey id, TUpdateInput input) public virtual async Task<TEntityDto> UpdateAsync(TKey id, TUpdateInput input)
{ {
CheckUpdatePermission(); CheckUpdatePermission();
@ -112,14 +112,14 @@ namespace Volo.Abp.Application.Services
return MapToEntityDto(entity); return MapToEntityDto(entity);
} }
public virtual Task DeleteAsync(TPrimaryKey id) public virtual Task DeleteAsync(TKey id)
{ {
CheckDeletePermission(); CheckDeletePermission();
return Repository.DeleteAsync(id); return Repository.DeleteAsync(id);
} }
protected virtual Task<TEntity> GetEntityByIdAsync(TPrimaryKey id) protected virtual Task<TEntity> GetEntityByIdAsync(TKey id)
{ {
return Repository.GetAsync(id); return Repository.GetAsync(id);
} }

52
src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs

@ -5,56 +5,56 @@ using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public abstract class CrudAppService<TEntity, TEntityDto, TPrimaryKey> public abstract class CrudAppService<TEntity, TEntityDto, TKey>
: CrudAppService<TEntity, TEntityDto, TPrimaryKey, PagedAndSortedResultRequestDto> : CrudAppService<TEntity, TEntityDto, TKey, PagedAndSortedResultRequestDto>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected CrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected CrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class CrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput> public abstract class CrudAppService<TEntity, TEntityDto, TKey, TGetAllInput>
: CrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TEntityDto, TEntityDto> : CrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TEntityDto, TEntityDto>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected CrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected CrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class CrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput> public abstract class CrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput>
: CrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TCreateInput> : CrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TCreateInput>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
where TCreateInput : IEntityDto<TPrimaryKey> where TCreateInput : IEntityDto<TKey>
{ {
protected CrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected CrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
} }
public abstract class CrudAppService<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput> public abstract class CrudAppService<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>
: CrudAppServiceBase<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput>, : CrudAppServiceBase<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>,
ICrudAppService<TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput> ICrudAppService<TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected CrudAppService(IQueryableRepository<TEntity, TPrimaryKey> repository) protected CrudAppService(IQueryableRepository<TEntity, TKey> repository)
: base(repository) : base(repository)
{ {
} }
public virtual TEntityDto Get(TPrimaryKey id) public virtual TEntityDto Get(TKey id)
{ {
CheckGetPermission(); CheckGetPermission();
@ -93,7 +93,7 @@ namespace Volo.Abp.Application.Services
return MapToEntityDto(entity); return MapToEntityDto(entity);
} }
public virtual TEntityDto Update(TPrimaryKey id, TUpdateInput input) public virtual TEntityDto Update(TKey id, TUpdateInput input)
{ {
CheckUpdatePermission(); CheckUpdatePermission();
@ -105,14 +105,14 @@ namespace Volo.Abp.Application.Services
return MapToEntityDto(entity); return MapToEntityDto(entity);
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
CheckDeletePermission(); CheckDeletePermission();
Repository.Delete(id); Repository.Delete(id);
} }
protected virtual TEntity GetEntityById(TPrimaryKey id) protected virtual TEntity GetEntityById(TKey id)
{ {
return Repository.Get(id); return Repository.Get(id);
} }

12
src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppServiceBase.cs

@ -11,11 +11,11 @@ namespace Volo.Abp.Application.Services
/// This is a common base class for CrudAppService and AsyncCrudAppService classes. /// This is a common base class for CrudAppService and AsyncCrudAppService classes.
/// Inherit either from CrudAppService or AsyncCrudAppService, not from this class. /// Inherit either from CrudAppService or AsyncCrudAppService, not from this class.
/// </summary> /// </summary>
public abstract class CrudAppServiceBase<TEntity, TEntityDto, TPrimaryKey, TGetAllInput, TCreateInput, TUpdateInput> : ApplicationService public abstract class CrudAppServiceBase<TEntity, TEntityDto, TKey, TGetAllInput, TCreateInput, TUpdateInput> : ApplicationService
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
protected IQueryableRepository<TEntity, TPrimaryKey> Repository { get; } protected IQueryableRepository<TEntity, TKey> Repository { get; }
protected virtual string GetPermissionName { get; set; } protected virtual string GetPermissionName { get; set; }
@ -27,7 +27,7 @@ namespace Volo.Abp.Application.Services
protected virtual string DeletePermissionName { get; set; } protected virtual string DeletePermissionName { get; set; }
protected CrudAppServiceBase(IQueryableRepository<TEntity, TPrimaryKey> repository) protected CrudAppServiceBase(IQueryableRepository<TEntity, TKey> repository)
{ {
Repository = repository; Repository = repository;
} }
@ -119,7 +119,7 @@ namespace Volo.Abp.Application.Services
} }
/// <summary> /// <summary>
/// Sets Id value for the entity if <see cref="TPrimaryKey"/> is <see cref="Guid"/>. /// Sets Id value for the entity if <see cref="TKey"/> is <see cref="Guid"/>.
/// It's used while creating a new entity. /// It's used while creating a new entity.
/// </summary> /// </summary>
protected virtual void SetIdForGuids(TEntity entity) protected virtual void SetIdForGuids(TEntity entity)

28
src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs

@ -3,39 +3,39 @@ using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public interface IAsyncCrudAppService<TEntityDto, in TPrimaryKey> public interface IAsyncCrudAppService<TEntityDto, in TKey>
: IAsyncCrudAppService<TEntityDto, TPrimaryKey, PagedAndSortedResultRequestDto> : IAsyncCrudAppService<TEntityDto, TKey, PagedAndSortedResultRequestDto>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface IAsyncCrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput> public interface IAsyncCrudAppService<TEntityDto, in TKey, in TGetListInput>
: IAsyncCrudAppService<TEntityDto, TPrimaryKey, TGetListInput, TEntityDto, TEntityDto> : IAsyncCrudAppService<TEntityDto, TKey, TGetListInput, TEntityDto, TEntityDto>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface IAsyncCrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput, in TCreateInput> public interface IAsyncCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput>
: IAsyncCrudAppService<TEntityDto, TPrimaryKey, TGetListInput, TCreateInput, TCreateInput> : IAsyncCrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface IAsyncCrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput, in TCreateInput, in TUpdateInput> public interface IAsyncCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput>
: IApplicationService : IApplicationService
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
Task<TEntityDto> GetAsync(TPrimaryKey id); Task<TEntityDto> GetAsync(TKey id);
Task<PagedResultDto<TEntityDto>> GetListAsync(TGetListInput input); Task<PagedResultDto<TEntityDto>> GetListAsync(TGetListInput input);
Task<TEntityDto> CreateAsync(TCreateInput input); Task<TEntityDto> CreateAsync(TCreateInput input);
Task<TEntityDto> UpdateAsync(TPrimaryKey id, TUpdateInput input); Task<TEntityDto> UpdateAsync(TKey id, TUpdateInput input);
Task DeleteAsync(TPrimaryKey id); Task DeleteAsync(TKey id);
} }
} }

28
src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs

@ -2,39 +2,39 @@ using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public interface ICrudAppService<TEntityDto, in TPrimaryKey> public interface ICrudAppService<TEntityDto, in TKey>
: ICrudAppService<TEntityDto, TPrimaryKey, PagedAndSortedResultRequestDto> : ICrudAppService<TEntityDto, TKey, PagedAndSortedResultRequestDto>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface ICrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput> public interface ICrudAppService<TEntityDto, in TKey, in TGetListInput>
: ICrudAppService<TEntityDto, TPrimaryKey, TGetListInput, TEntityDto, TEntityDto> : ICrudAppService<TEntityDto, TKey, TGetListInput, TEntityDto, TEntityDto>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface ICrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput, in TCreateInput> public interface ICrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput>
: ICrudAppService<TEntityDto, TPrimaryKey, TGetListInput, TCreateInput, TCreateInput> : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput>
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
} }
public interface ICrudAppService<TEntityDto, in TPrimaryKey, in TGetListInput, in TCreateInput, in TUpdateInput> public interface ICrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput>
: IApplicationService : IApplicationService
where TEntityDto : IEntityDto<TPrimaryKey> where TEntityDto : IEntityDto<TKey>
{ {
TEntityDto Get(TPrimaryKey id); TEntityDto Get(TKey id);
PagedResultDto<TEntityDto> GetAll(TGetListInput input); PagedResultDto<TEntityDto> GetAll(TGetListInput input);
TEntityDto Create(TCreateInput input); TEntityDto Create(TCreateInput input);
TEntityDto Update(TPrimaryKey id, TUpdateInput input); TEntityDto Update(TKey id, TUpdateInput input);
void Delete(TPrimaryKey id); void Delete(TKey id);
} }
} }

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

@ -19,7 +19,7 @@ namespace Volo.Abp.DependencyInjection
public Type DefaultRepositoryImplementationType { get; private set; } public Type DefaultRepositoryImplementationType { get; private set; }
public Type DefaultRepositoryImplementationTypeWithoutPrimaryKey { get; private set; } public Type DefaultRepositoryImplementationTypeWithouTKey { get; private set; }
public bool RegisterDefaultRepositories { get; private set; } public bool RegisterDefaultRepositories { get; private set; }
@ -27,7 +27,7 @@ namespace Volo.Abp.DependencyInjection
public Dictionary<Type, Type> CustomRepositories { get; } public Dictionary<Type, Type> CustomRepositories { get; }
public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithoutPrimaryKey != null; public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithouTKey != null;
protected CommonDbContextRegistrationOptions(Type originalDbContextType) protected CommonDbContextRegistrationOptions(Type originalDbContextType)
{ {
@ -88,14 +88,14 @@ namespace Volo.Abp.DependencyInjection
public ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses( public ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses(
Type repositoryImplementationType, Type repositoryImplementationType,
Type repositoryImplementationTypeWithoutPrimaryKey Type repositoryImplementationTypeWithouTKey
) )
{ {
Check.NotNull(repositoryImplementationType, nameof(repositoryImplementationType)); Check.NotNull(repositoryImplementationType, nameof(repositoryImplementationType));
Check.NotNull(repositoryImplementationTypeWithoutPrimaryKey, nameof(repositoryImplementationTypeWithoutPrimaryKey)); Check.NotNull(repositoryImplementationTypeWithouTKey, nameof(repositoryImplementationTypeWithouTKey));
DefaultRepositoryImplementationType = repositoryImplementationType; DefaultRepositoryImplementationType = repositoryImplementationType;
DefaultRepositoryImplementationTypeWithoutPrimaryKey = repositoryImplementationTypeWithoutPrimaryKey; DefaultRepositoryImplementationTypeWithouTKey = repositoryImplementationTypeWithouTKey;
return this; return this;
} }

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

@ -48,9 +48,9 @@ namespace Volo.Abp.DependencyInjection
/// 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> /// <param name="repositoryImplementationTypeWithouTKey">Repository implementation type (without primary key)</param>
/// <returns></returns> /// <returns></returns>
ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType, [NotNull] Type repositoryImplementationTypeWithoutPrimaryKey); ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType, [NotNull] Type repositoryImplementationTypeWithouTKey);
/// <summary> /// <summary>
/// Replaces given DbContext type with this DbContext type. /// Replaces given DbContext type with this DbContext type.

4
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs

@ -7,8 +7,8 @@
} }
/// <inheritdoc cref="IAggregateRoot{TPrimaryKey}" /> /// <inheritdoc cref="IAggregateRoot{TKey}" />
public abstract class AggregateRoot<TPrimaryKey> : Entity<TPrimaryKey>, IAggregateRoot<TPrimaryKey> public abstract class AggregateRoot<TKey> : Entity<TKey>, IAggregateRoot<TKey>
{ {
} }

14
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs

@ -12,16 +12,16 @@ namespace Volo.Abp.Domain.Entities
} }
} }
/// <inheritdoc cref="IEntity{TPrimaryKey}" /> /// <inheritdoc cref="IEntity{TKey}" />
public abstract class Entity<TPrimaryKey> : Entity, IEntity<TPrimaryKey> public abstract class Entity<TKey> : Entity, IEntity<TKey>
{ {
/// <inheritdoc/> /// <inheritdoc/>
public virtual TPrimaryKey Id { get; set; } public virtual TKey Id { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null || !(obj is Entity<TPrimaryKey>)) if (obj == null || !(obj is Entity<TKey>))
{ {
return false; return false;
} }
@ -33,7 +33,7 @@ namespace Volo.Abp.Domain.Entities
} }
//Transient objects are not considered as equal //Transient objects are not considered as equal
var other = (Entity<TPrimaryKey>)obj; var other = (Entity<TKey>)obj;
if (EntityHelper.IsTransient(this) && EntityHelper.IsTransient(other)) if (EntityHelper.IsTransient(this) && EntityHelper.IsTransient(other))
{ {
return false; return false;
@ -61,7 +61,7 @@ namespace Volo.Abp.Domain.Entities
return Id.GetHashCode(); return Id.GetHashCode();
} }
public static bool operator ==(Entity<TPrimaryKey> left, Entity<TPrimaryKey> right) public static bool operator ==(Entity<TKey> left, Entity<TKey> right)
{ {
if (Equals(left, null)) if (Equals(left, null))
{ {
@ -71,7 +71,7 @@ namespace Volo.Abp.Domain.Entities
return left.Equals(right); return left.Equals(right);
} }
public static bool operator !=(Entity<TPrimaryKey> left, Entity<TPrimaryKey> right) public static bool operator !=(Entity<TKey> left, Entity<TKey> right)
{ {
return !(left == right); return !(left == right);
} }

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

@ -16,20 +16,20 @@ namespace Volo.Abp.Domain.Entities
return typeof(IEntity).IsAssignableFrom(type); return typeof(IEntity).IsAssignableFrom(type);
} }
public static bool IsTransient<TPrimaryKey>(IEntity<TPrimaryKey> entity) // TODO: Completely remove IsTransient public static bool IsTransient<TKey>(IEntity<TKey> entity) // TODO: Completely remove IsTransient
{ {
if (EqualityComparer<TPrimaryKey>.Default.Equals(entity.Id, default)) if (EqualityComparer<TKey>.Default.Equals(entity.Id, default))
{ {
return true; return true;
} }
//Workaround for EF Core since it sets int/long to min value when attaching to dbcontext //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext
if (typeof(TPrimaryKey) == typeof(int)) if (typeof(TKey) == typeof(int))
{ {
return Convert.ToInt32(entity.Id) <= 0; return Convert.ToInt32(entity.Id) <= 0;
} }
if (typeof(TPrimaryKey) == typeof(long)) if (typeof(TKey) == typeof(long))
{ {
return Convert.ToInt64(entity.Id) <= 0; return Convert.ToInt64(entity.Id) <= 0;
} }
@ -39,7 +39,7 @@ namespace Volo.Abp.Domain.Entities
/// <summary> /// <summary>
/// Tries to find the primary key type of the 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}"/> /// May return null if given type does not implement <see cref="IEntity{TKey}"/>
/// </summary> /// </summary>
[CanBeNull] [CanBeNull]
public static Type FindPrimaryKeyType<TEntity>() public static Type FindPrimaryKeyType<TEntity>()
@ -50,7 +50,7 @@ namespace Volo.Abp.Domain.Entities
/// <summary> /// <summary>
/// Tries to find the primary key type of the 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}"/> /// May return null if given type does not implement <see cref="IEntity{TKey}"/>
/// </summary> /// </summary>
[CanBeNull] [CanBeNull]
public static Type FindPrimaryKeyType([NotNull] Type entityType) public static Type FindPrimaryKeyType([NotNull] Type entityType)
@ -71,13 +71,13 @@ namespace Volo.Abp.Domain.Entities
return null; return null;
} }
public static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId<TEntity, TPrimaryKey>(TPrimaryKey id) public static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId<TEntity, TKey>(TKey id)
where TEntity : IEntity<TPrimaryKey> where TEntity : IEntity<TKey>
{ {
var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaParam = Expression.Parameter(typeof(TEntity));
var lambdaBody = Expression.Equal( var lambdaBody = Expression.Equal(
Expression.PropertyOrField(lambdaParam, "Id"), Expression.PropertyOrField(lambdaParam, "Id"),
Expression.Constant(id, typeof(TPrimaryKey)) Expression.Constant(id, typeof(TKey))
); );
return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam); return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);

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

@ -2,7 +2,7 @@
{ {
/// <summary> /// <summary>
/// Defines an aggregate root. It's primary key may not be "Id" or it may have a composite primary key. /// Defines an aggregate root. It's primary key may not be "Id" or it may have a composite primary key.
/// Use <see cref="IAggregateRoot{TPrimaryKey}"/> where possible for better integration to repositories and other structures in the framework. /// Use <see cref="IAggregateRoot{TKey}"/> where possible for better integration to repositories and other structures in the framework.
/// </summary> /// </summary>
public interface IAggregateRoot : IEntity public interface IAggregateRoot : IEntity
{ {
@ -12,8 +12,8 @@
/// <summary> /// <summary>
/// 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="TKey">Type of the primary key of the entity</typeparam>
public interface IAggregateRoot<TPrimaryKey> : IEntity<TPrimaryKey>, IAggregateRoot public interface IAggregateRoot<TKey> : IEntity<TKey>, IAggregateRoot
{ {
} }

8
src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs

@ -2,7 +2,7 @@
{ {
/// <summary> /// <summary>
/// Defines an entity. It's primary key may not be "Id" or it mah have a composite primary key. /// Defines an entity. It's primary key may not be "Id" or it mah have a composite primary key.
/// Use <see cref="IEntity{TPrimaryKey}"/> where possible for better integration to repositories and other structures in the framework. /// Use <see cref="IEntity{TKey}"/> where possible for better integration to repositories and other structures in the framework.
/// </summary> /// </summary>
public interface IEntity public interface IEntity
{ {
@ -12,12 +12,12 @@
/// <summary> /// <summary>
/// Defines an entity with a single primary key with "Id" property. /// Defines an entity with a single primary key with "Id" property.
/// </summary> /// </summary>
/// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam> /// <typeparam name="TKey">Type of the primary key of the entity</typeparam>
public interface IEntity<TPrimaryKey> : IEntity public interface IEntity<TKey> : IEntity
{ {
/// <summary> /// <summary>
/// Unique identifier for this entity. /// Unique identifier for this entity.
/// </summary> /// </summary>
TPrimaryKey Id { get; set; } TKey Id { get; set; }
} }
} }

4
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs

@ -31,8 +31,8 @@ namespace Volo.Abp.Domain.Repositories
Task DeleteAsync([NotNull] Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default); Task DeleteAsync([NotNull] Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
} }
public interface IQueryableRepository<TEntity, TPrimaryKey> : IQueryableRepository<TEntity>, IRepository<TEntity, TPrimaryKey> public interface IQueryableRepository<TEntity, TKey> : IQueryableRepository<TEntity>, IRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
} }
} }

16
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IRepository.cs

@ -69,8 +69,8 @@ namespace Volo.Abp.Domain.Repositories
Task DeleteAsync([NotNull] TEntity entity, CancellationToken cancellationToken = default); //TODO: Return true if deleted Task DeleteAsync([NotNull] TEntity entity, CancellationToken cancellationToken = default); //TODO: Return true if deleted
} }
public interface IRepository<TEntity, TPrimaryKey> : IRepository<TEntity> public interface IRepository<TEntity, TKey> : IRepository<TEntity>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
/// <summary> /// <summary>
/// Gets an entity with given primary key. /// Gets an entity with given primary key.
@ -79,7 +79,7 @@ namespace Volo.Abp.Domain.Repositories
/// <param name="id">Primary key of the entity to get</param> /// <param name="id">Primary key of the entity to get</param>
/// <returns>Entity</returns> /// <returns>Entity</returns>
[NotNull] [NotNull]
TEntity Get(TPrimaryKey id); TEntity Get(TKey id);
/// <summary> /// <summary>
/// Gets an entity with given primary key. /// Gets an entity with given primary key.
@ -89,7 +89,7 @@ namespace Volo.Abp.Domain.Repositories
/// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param> /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>Entity</returns> /// <returns>Entity</returns>
[NotNull] [NotNull]
Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default); Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Gets an entity with given primary key or null if not found. /// Gets an entity with given primary key or null if not found.
@ -97,7 +97,7 @@ namespace Volo.Abp.Domain.Repositories
/// <param name="id">Primary key of the entity to get</param> /// <param name="id">Primary key of the entity to get</param>
/// <returns>Entity or null</returns> /// <returns>Entity or null</returns>
[CanBeNull] [CanBeNull]
TEntity Find(TPrimaryKey id); TEntity Find(TKey id);
/// <summary> /// <summary>
/// Gets an entity with given primary key or null if not found. /// Gets an entity with given primary key or null if not found.
@ -105,19 +105,19 @@ namespace Volo.Abp.Domain.Repositories
/// <param name="id">Primary key of the entity to get</param> /// <param name="id">Primary key of the entity to get</param>
/// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param> /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>Entity or null</returns> /// <returns>Entity or null</returns>
Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default); Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Deletes an entity by primary key. /// Deletes an entity by primary key.
/// </summary> /// </summary>
/// <param name="id">Primary key of the entity</param> /// <param name="id">Primary key of the entity</param>
void Delete(TPrimaryKey id); //TODO: Return true if deleted void Delete(TKey id); //TODO: Return true if deleted
/// <summary> /// <summary>
/// Deletes an entity by primary key. /// Deletes an entity by primary key.
/// </summary> /// </summary>
/// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param> /// <param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <param name="id">Primary key of the entity</param> /// <param name="id">Primary key of the entity</param>
Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default); //TODO: Return true if deleted Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); //TODO: Return true if deleted
} }
} }

4
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs

@ -7,8 +7,8 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories namespace Volo.Abp.Domain.Repositories
{ {
public interface ISupportsExplicitLoading<TEntity, TPrimaryKey> public interface ISupportsExplicitLoading<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
Task EnsureCollectionLoadedAsync<TProperty>( Task EnsureCollectionLoadedAsync<TProperty>(
TEntity entity, TEntity entity,

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

@ -68,15 +68,15 @@ namespace Volo.Abp.Domain.Repositories
} }
} }
public abstract class QueryableRepositoryBase<TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity>, IQueryableRepository<TEntity, TPrimaryKey> public abstract class QueryableRepositoryBase<TEntity, TKey> : QueryableRepositoryBase<TEntity>, IQueryableRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public virtual TEntity Find(TPrimaryKey id) public virtual TEntity Find(TKey id)
{ {
return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TPrimaryKey>(id)); return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TKey>(id));
} }
public virtual TEntity Get(TPrimaryKey id) public virtual TEntity Get(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
@ -88,17 +88,17 @@ namespace Volo.Abp.Domain.Repositories
return entity; return entity;
} }
public virtual Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Get(id)); return Task.FromResult(Get(id));
} }
public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Find(id)); return Task.FromResult(Find(id));
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
if (entity == null) if (entity == null)
@ -109,7 +109,7 @@ namespace Volo.Abp.Domain.Repositories
Delete(entity); Delete(entity);
} }
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
Delete(id); Delete(id);
return Task.CompletedTask; return Task.CompletedTask;

16
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs

@ -43,10 +43,10 @@ namespace Volo.Abp.Domain.Repositories
} }
} }
public abstract class RepositoryBase<TEntity, TPrimaryKey> : RepositoryBase<TEntity>, IRepository<TEntity, TPrimaryKey> public abstract class RepositoryBase<TEntity, TKey> : RepositoryBase<TEntity>, IRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public virtual TEntity Get(TPrimaryKey id) public virtual TEntity Get(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
@ -58,19 +58,19 @@ namespace Volo.Abp.Domain.Repositories
return entity; return entity;
} }
public virtual Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Get(id)); return Task.FromResult(Get(id));
} }
public abstract TEntity Find(TPrimaryKey id); public abstract TEntity Find(TKey id);
public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Find(id)); return Task.FromResult(Find(id));
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
if (entity == null) if (entity == null)
@ -81,7 +81,7 @@ namespace Volo.Abp.Domain.Repositories
Delete(entity); Delete(entity);
} }
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
Delete(id); Delete(id);
return Task.CompletedTask; return Task.CompletedTask;

28
src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs

@ -11,55 +11,55 @@ namespace Volo.Abp.Domain.Repositories
{ {
public static class RepositoryExtensions public static class RepositoryExtensions
{ {
public static async Task EnsureCollectionLoadedAsync<TEntity, TPrimaryKey, TProperty>( public static async Task EnsureCollectionLoadedAsync<TEntity, TKey, TProperty>(
this IRepository<TEntity, TPrimaryKey> repository, this IRepository<TEntity, TKey> repository,
TEntity entity, TEntity entity,
Expression<Func<TEntity, IEnumerable<TProperty>>> propertyExpression, Expression<Func<TEntity, IEnumerable<TProperty>>> propertyExpression,
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
) )
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TProperty : class where TProperty : class
{ {
var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading<TEntity, TPrimaryKey>; var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading<TEntity, TKey>;
if (repo != null) if (repo != null)
{ {
await repo.EnsureCollectionLoadedAsync(entity, propertyExpression, cancellationToken); await repo.EnsureCollectionLoadedAsync(entity, propertyExpression, cancellationToken);
} }
} }
public static void EnsureCollectionLoaded<TEntity, TPrimaryKey, TProperty>( public static void EnsureCollectionLoaded<TEntity, TKey, TProperty>(
this IRepository<TEntity, TPrimaryKey> repository, this IRepository<TEntity, TKey> repository,
TEntity entity, TEntity entity,
Expression<Func<TEntity, IEnumerable<TProperty>>> propertyExpression Expression<Func<TEntity, IEnumerable<TProperty>>> propertyExpression
) )
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TProperty : class where TProperty : class
{ {
AsyncHelper.RunSync(() => repository.EnsureCollectionLoadedAsync(entity, propertyExpression)); AsyncHelper.RunSync(() => repository.EnsureCollectionLoadedAsync(entity, propertyExpression));
} }
public static async Task EnsurePropertyLoadedAsync<TEntity, TPrimaryKey, TProperty>( public static async Task EnsurePropertyLoadedAsync<TEntity, TKey, TProperty>(
this IRepository<TEntity, TPrimaryKey> repository, this IRepository<TEntity, TKey> repository,
TEntity entity, TEntity entity,
Expression<Func<TEntity, TProperty>> propertyExpression, Expression<Func<TEntity, TProperty>> propertyExpression,
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
) )
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TProperty : class where TProperty : class
{ {
var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading<TEntity, TPrimaryKey>; var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading<TEntity, TKey>;
if (repo != null) if (repo != null)
{ {
await repo.EnsurePropertyLoadedAsync(entity, propertyExpression, cancellationToken); await repo.EnsurePropertyLoadedAsync(entity, propertyExpression, cancellationToken);
} }
} }
public static void EnsurePropertyLoaded<TEntity, TPrimaryKey, TProperty>( public static void EnsurePropertyLoaded<TEntity, TKey, TProperty>(
this IRepository<TEntity, TPrimaryKey> repository, this IRepository<TEntity, TKey> repository,
TEntity entity, TEntity entity,
Expression<Func<TEntity, TProperty>> propertyExpression Expression<Func<TEntity, TProperty>> propertyExpression
) )
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
where TProperty : class where TProperty : class
{ {
AsyncHelper.RunSync(() => repository.EnsurePropertyLoadedAsync(entity, propertyExpression)); AsyncHelper.RunSync(() => repository.EnsurePropertyLoadedAsync(entity, propertyExpression));

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

@ -57,7 +57,7 @@ namespace Volo.Abp.Domain.Repositories
if (primaryKeyType == null) if (primaryKeyType == null)
{ {
return Options.SpecifiedDefaultRepositoryTypes return Options.SpecifiedDefaultRepositoryTypes
? Options.DefaultRepositoryImplementationTypeWithoutPrimaryKey.MakeGenericType(entityType) ? Options.DefaultRepositoryImplementationTypeWithouTKey.MakeGenericType(entityType)
: GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType); : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType);
} }

16
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs

@ -7,25 +7,25 @@ namespace Volo.Abp.Domain.Repositories
{ {
public static class EfCoreRepositoryExtensions public static class EfCoreRepositoryExtensions
{ {
public static DbContext GetDbContext<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static DbContext GetDbContext<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToEfCoreRepository().DbContext; return repository.ToEfCoreRepository().DbContext;
} }
public static DbSet<TEntity> GetDbSet<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static DbSet<TEntity> GetDbSet<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToEfCoreRepository().DbSet; return repository.ToEfCoreRepository().DbSet;
} }
public static IEfCoreRepository<TEntity, TPrimaryKey> ToEfCoreRepository<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IEfCoreRepository<TEntity, TKey> ToEfCoreRepository<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
var efCoreRepository = repository as IEfCoreRepository<TEntity, TPrimaryKey>; var efCoreRepository = repository as IEfCoreRepository<TEntity, TKey>;
if (efCoreRepository == null) if (efCoreRepository == null)
{ {
throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository<TEntity, TPrimaryKey>).AssemblyQualifiedName, nameof(repository)); throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository<TEntity, TKey>).AssemblyQualifiedName, nameof(repository));
} }
return efCoreRepository; return efCoreRepository;

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

@ -95,12 +95,12 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
} }
} }
public class EfCoreRepository<TDbContext, TEntity, TPrimaryKey> : EfCoreRepository<TDbContext, TEntity>, public class EfCoreRepository<TDbContext, TEntity, TKey> : EfCoreRepository<TDbContext, TEntity>,
IEfCoreRepository<TEntity, TPrimaryKey>, IEfCoreRepository<TEntity, TKey>,
ISupportsExplicitLoading<TEntity, TPrimaryKey> ISupportsExplicitLoading<TEntity, TKey>
where TDbContext : IEfCoreDbContext where TDbContext : IEfCoreDbContext
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider) public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider)
: base(dbContextProvider) : base(dbContextProvider)
@ -108,7 +108,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
} }
public TEntity Get(TPrimaryKey id) public TEntity Get(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
@ -120,7 +120,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return entity; return entity;
} }
public virtual async Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual async Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
var entity = await FindAsync(id, GetCancellationToken(cancellationToken)); var entity = await FindAsync(id, GetCancellationToken(cancellationToken));
@ -132,17 +132,17 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
return entity; return entity;
} }
public virtual TEntity Find(TPrimaryKey id) public virtual TEntity Find(TKey id)
{ {
return DbSet.Find(id); return DbSet.Find(id);
} }
public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken)); return DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken));
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
if (entity == null) if (entity == null)
@ -153,7 +153,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
Delete(entity); Delete(entity);
} }
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
Delete(id); Delete(id);
return Task.CompletedTask; return Task.CompletedTask;

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

@ -11,8 +11,8 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
DbSet<TEntity> DbSet { get; } DbSet<TEntity> DbSet { get; }
} }
public interface IEfCoreRepository<TEntity, TPrimaryKey> : IEfCoreRepository<TEntity>, IQueryableRepository<TEntity, TPrimaryKey> public interface IEfCoreRepository<TEntity, TKey> : IEfCoreRepository<TEntity>, IQueryableRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
} }

2
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs

@ -6,6 +6,6 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
{ {
List<TEntity> Collection<TEntity>(); List<TEntity> Collection<TEntity>();
TPrimaryKey GenerateNextId<TEntity, TPrimaryKey>(); TKey GenerateNextId<TEntity, TKey>();
} }
} }

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

@ -11,8 +11,8 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
List<TEntity> Collection { get; } List<TEntity> Collection { get; }
} }
public interface IMemoryDbRepository<TEntity, TPrimaryKey> : IMemoryDbRepository<TEntity>, IQueryableRepository<TEntity, TPrimaryKey> public interface IMemoryDbRepository<TEntity, TKey> : IMemoryDbRepository<TEntity>, IQueryableRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
} }

16
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/InMemoryIdGenerator.cs

@ -8,24 +8,24 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
private int _lastInt; private int _lastInt;
private long _lastLong; private long _lastLong;
public TPrimaryKey GenerateNext<TPrimaryKey>() public TKey GenerateNext<TKey>()
{ {
if (typeof(TPrimaryKey) == typeof(Guid)) if (typeof(TKey) == typeof(Guid))
{ {
return (TPrimaryKey)(object)Guid.NewGuid(); return (TKey)(object)Guid.NewGuid();
} }
if (typeof(TPrimaryKey) == typeof(int)) if (typeof(TKey) == typeof(int))
{ {
return (TPrimaryKey)(object)Interlocked.Increment(ref _lastInt); return (TKey)(object)Interlocked.Increment(ref _lastInt);
} }
if (typeof(TPrimaryKey) == typeof(long)) if (typeof(TKey) == typeof(long))
{ {
return (TPrimaryKey)(object)Interlocked.Increment(ref _lastLong); return (TKey)(object)Interlocked.Increment(ref _lastLong);
} }
throw new AbpException("Not supported PrimaryKey type: " + typeof(TPrimaryKey).FullName); throw new AbpException("Not supported PrimaryKey type: " + typeof(TKey).FullName);
} }
} }
} }

4
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs

@ -21,11 +21,11 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
return _sets.GetOrAdd(typeof(TEntity), _ => new List<TEntity>()) as List<TEntity>; return _sets.GetOrAdd(typeof(TEntity), _ => new List<TEntity>()) as List<TEntity>;
} }
public TPrimaryKey GenerateNextId<TEntity, TPrimaryKey>() public TKey GenerateNextId<TEntity, TKey>()
{ {
return _idGenerators return _idGenerators
.GetOrAdd(typeof(TEntity), () => new InMemoryIdGenerator()) .GetOrAdd(typeof(TEntity), () => new InMemoryIdGenerator())
.GenerateNext<TPrimaryKey>(); .GenerateNext<TKey>();
} }
} }
} }

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

@ -45,9 +45,9 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
} }
} }
public class MemoryDbRepository<TMemoryDbContext, TEntity, TPrimaryKey> : MemoryDbRepository<TMemoryDbContext, TEntity>, IMemoryDbRepository<TEntity, TPrimaryKey> public class MemoryDbRepository<TMemoryDbContext, TEntity, TKey> : MemoryDbRepository<TMemoryDbContext, TEntity>, IMemoryDbRepository<TEntity, TKey>
where TMemoryDbContext : MemoryDbContext where TMemoryDbContext : MemoryDbContext
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public MemoryDbRepository(IMemoryDatabaseProvider<TMemoryDbContext> databaseProvider) public MemoryDbRepository(IMemoryDatabaseProvider<TMemoryDbContext> databaseProvider)
: base(databaseProvider) : base(databaseProvider)
@ -62,21 +62,21 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
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(TKey) == typeof(int) || typeof(TKey) == typeof(long) || typeof(TKey) == typeof(Guid))
{ {
if (EntityHelper.IsTransient(entity)) if (EntityHelper.IsTransient(entity))
{ {
entity.Id = Database.GenerateNextId<TEntity, TPrimaryKey>(); entity.Id = Database.GenerateNextId<TEntity, TKey>();
} }
} }
} }
public virtual TEntity Find(TPrimaryKey id) public virtual TEntity Find(TKey id)
{ {
return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TPrimaryKey>(id)); return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId<TEntity, TKey>(id));
} }
public virtual TEntity Get(TPrimaryKey id) public virtual TEntity Get(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
@ -88,17 +88,17 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
return entity; return entity;
} }
public virtual Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Get(id)); return Task.FromResult(Get(id));
} }
public virtual Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Find(id)); return Task.FromResult(Find(id));
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
if (entity == null) if (entity == null)
@ -109,7 +109,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
Delete(entity); Delete(entity);
} }
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
Delete(id); Delete(id);
return Task.CompletedTask; return Task.CompletedTask;

16
src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs

@ -7,25 +7,25 @@ namespace Volo.Abp.Domain.Repositories
{ {
public static class MemoryDbCoreRepositoryExtensions public static class MemoryDbCoreRepositoryExtensions
{ {
public static IMemoryDatabase GetDatabase<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IMemoryDatabase GetDatabase<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMemoryDbRepository().Database; return repository.ToMemoryDbRepository().Database;
} }
public static List<TEntity> GetCollection<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static List<TEntity> GetCollection<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMemoryDbRepository().Collection; return repository.ToMemoryDbRepository().Collection;
} }
public static IMemoryDbRepository<TEntity, TPrimaryKey> ToMemoryDbRepository<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IMemoryDbRepository<TEntity, TKey> ToMemoryDbRepository<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
var memoryDbRepository = repository as IMemoryDbRepository<TEntity, TPrimaryKey>; var memoryDbRepository = repository as IMemoryDbRepository<TEntity, TKey>;
if (memoryDbRepository == null) if (memoryDbRepository == null)
{ {
throw new ArgumentException("Given repository does not implement " + typeof(IMemoryDbRepository<TEntity, TPrimaryKey>).AssemblyQualifiedName, nameof(repository)); throw new ArgumentException("Given repository does not implement " + typeof(IMemoryDbRepository<TEntity, TKey>).AssemblyQualifiedName, nameof(repository));
} }
return memoryDbRepository; return memoryDbRepository;

4
src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs

@ -13,8 +13,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
string CollectionName { get; } string CollectionName { get; }
} }
public interface IMongoDbRepository<TEntity, TPrimaryKey> : IMongoDbRepository<TEntity>, IQueryableRepository<TEntity, TPrimaryKey> public interface IMongoDbRepository<TEntity, TKey> : IMongoDbRepository<TEntity>, IQueryableRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
} }

18
src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs

@ -81,9 +81,9 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
} }
} }
public class MongoDbRepository<TMongoDbContext, TEntity, TPrimaryKey> : MongoDbRepository<TMongoDbContext, TEntity>, IMongoDbRepository<TEntity, TPrimaryKey> public class MongoDbRepository<TMongoDbContext, TEntity, TKey> : MongoDbRepository<TMongoDbContext, TEntity>, IMongoDbRepository<TEntity, TKey>
where TMongoDbContext : AbpMongoDbContext where TMongoDbContext : AbpMongoDbContext
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public MongoDbRepository(IMongoDatabaseProvider<TMongoDbContext> databaseProvider) public MongoDbRepository(IMongoDatabaseProvider<TMongoDbContext> databaseProvider)
: base(databaseProvider) : base(databaseProvider)
@ -91,7 +91,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
} }
public virtual TEntity Get(TPrimaryKey id) public virtual TEntity Get(TKey id)
{ {
var entity = Find(id); var entity = Find(id);
@ -103,7 +103,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
return entity; return entity;
} }
public virtual async Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual async Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
var entity = await FindAsync(id, cancellationToken); var entity = await FindAsync(id, cancellationToken);
@ -115,22 +115,22 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
return entity; return entity;
} }
public virtual void Delete(TPrimaryKey id) public virtual void Delete(TKey id)
{ {
Collection.DeleteOne(CreateEntityFilter(id)); Collection.DeleteOne(CreateEntityFilter(id));
} }
public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return Collection.DeleteOneAsync(CreateEntityFilter(id), cancellationToken); return Collection.DeleteOneAsync(CreateEntityFilter(id), cancellationToken);
} }
public virtual async Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public virtual async Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
return await Collection.Find(CreateEntityFilter(id)).FirstOrDefaultAsync(cancellationToken); return await Collection.Find(CreateEntityFilter(id)).FirstOrDefaultAsync(cancellationToken);
} }
public virtual TEntity Find(TPrimaryKey id) public virtual TEntity Find(TKey id)
{ {
return Collection.Find(CreateEntityFilter(id)).FirstOrDefault(); return Collection.Find(CreateEntityFilter(id)).FirstOrDefault();
} }
@ -140,7 +140,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
return Builders<TEntity>.Filter.Eq(e => e.Id, entity.Id); return Builders<TEntity>.Filter.Eq(e => e.Id, entity.Id);
} }
private static FilterDefinition<TEntity> CreateEntityFilter(TPrimaryKey id) private static FilterDefinition<TEntity> CreateEntityFilter(TKey id)
{ {
return Builders<TEntity>.Filter.Eq(e => e.Id, id); return Builders<TEntity>.Filter.Eq(e => e.Id, id);
} }

20
src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs

@ -7,31 +7,31 @@ namespace Volo.Abp.Domain.Repositories
{ {
public static class MongoDbCoreRepositoryExtensions public static class MongoDbCoreRepositoryExtensions
{ {
public static IMongoDatabase GetDatabase<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IMongoDatabase GetDatabase<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMongoDbRepository().Database; return repository.ToMongoDbRepository().Database;
} }
public static IMongoCollection<TEntity> GetCollection<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IMongoCollection<TEntity> GetCollection<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMongoDbRepository().Collection; return repository.ToMongoDbRepository().Collection;
} }
public static string GetCollectionName<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static string GetCollectionName<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
return repository.ToMongoDbRepository().CollectionName; return repository.ToMongoDbRepository().CollectionName;
} }
public static IMongoDbRepository<TEntity, TPrimaryKey> ToMongoDbRepository<TEntity, TPrimaryKey>(this IRepository<TEntity, TPrimaryKey> repository) public static IMongoDbRepository<TEntity, TKey> ToMongoDbRepository<TEntity, TKey>(this IRepository<TEntity, TKey> repository)
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
var mongoDbRepository = repository as IMongoDbRepository<TEntity, TPrimaryKey>; var mongoDbRepository = repository as IMongoDbRepository<TEntity, TKey>;
if (mongoDbRepository == null) if (mongoDbRepository == null)
{ {
throw new ArgumentException("Given repository does not implement " + typeof(IMongoDbRepository<TEntity, TPrimaryKey>).AssemblyQualifiedName, nameof(repository)); throw new ArgumentException("Given repository does not implement " + typeof(IMongoDbRepository<TEntity, TKey>).AssemblyQualifiedName, nameof(repository));
} }
return mongoDbRepository; return mongoDbRepository;

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

@ -169,35 +169,35 @@ namespace Volo.Abp.Domain.Repositories
} }
} }
public class MyTestDefaultRepository<TEntity, TPrimaryKey> : MyTestDefaultRepository<TEntity>, IRepository<TEntity, TPrimaryKey> public class MyTestDefaultRepository<TEntity, TKey> : MyTestDefaultRepository<TEntity>, IRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
public TEntity Get(TPrimaryKey id) public TEntity Get(TKey id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<TEntity> GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public TEntity Find(TPrimaryKey id) public TEntity Find(TKey id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<TEntity> FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public Task<TEntity> FindAsync(TKey id, CancellationToken cancellationToken = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void Delete(TPrimaryKey id) public void Delete(TKey id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) public Task DeleteAsync(TKey id, CancellationToken cancellationToken = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -214,8 +214,8 @@ namespace Volo.Abp.Domain.Repositories
} }
public class MyTestCustomBaseRepository<TEntity, TPrimaryKey> : MyTestDefaultRepository<TEntity, TPrimaryKey> public class MyTestCustomBaseRepository<TEntity, TKey> : MyTestDefaultRepository<TEntity, TKey>
where TEntity : class, IEntity<TPrimaryKey> where TEntity : class, IEntity<TKey>
{ {
} }

72
test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TestApp.Domain namespace Volo.Abp.TestApp.Domain
@ -25,4 +27,74 @@ namespace Volo.Abp.TestApp.Domain
Type = type; Type = type;
} }
} }
public class Order : AggregateRoot<Guid>
{
public virtual string ReferenceNo { get; protected set; }
public virtual float TotalItemCount { get; protected set; }
public virtual DateTime CreationTime { get; protected set; }
public virtual List<OrderLine> OrderLines { get; protected set; }
protected Order()
{
}
public Order(Guid id, string referenceNo)
{
Id = id;
ReferenceNo = referenceNo;
OrderLines = new List<OrderLine>();
}
public void AddProduct(Guid productId, int count)
{
if (count <= 0)
{
throw new ArgumentException("You can not add zero or negative count of products!", nameof(count));
}
var existingLine = OrderLines.FirstOrDefault(ol => ol.ProductId == productId);
if (existingLine == null)
{
OrderLines.Add(new OrderLine(this.Id, productId, count));
}
else
{
existingLine.ChangeCount(existingLine.Count + count);
}
TotalItemCount += count;
}
}
public class OrderLine : Entity
{
public virtual Guid OrderId { get; protected set; }
public virtual Guid ProductId { get; protected set; }
public virtual int Count { get; protected set; }
protected OrderLine()
{
}
public OrderLine(Guid orderId, Guid productId, int count)
{
OrderId = orderId;
ProductId = productId;
Count = count;
}
internal void ChangeCount(int newCount)
{
Count = newCount;
}
}
} }
Loading…
Cancel
Save