diff --git a/docs/Entities.md b/docs/Entities.md new file mode 100644 index 0000000000..67e3856e7b --- /dev/null +++ b/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` class as shown below: + +```C# +public class Person : Entity +{ + 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` class, you can directly implement `IEntity` interface. + +`Entity` 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` for these entities. However, you can always use `IRepository`. 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 +{ + public virtual string ReferenceNo { get; protected set; } + + public virtual int TotalItemCount { get; protected set; } + + public virtual DateTime CreationTime { get; protected set; } + + public virtual List OrderLines { get; protected set; } + + protected Order() + { + + } + + public Order(Guid id, string referenceNo) + { + Id = id; + ReferenceNo = referenceNo; + OrderLines = new List(); + } + + 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`). +* ... + diff --git a/src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs b/src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs index 1e75094169..e6203386ae 100644 --- a/src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs +++ b/src/Volo.Abp.Ddd/Microsoft/Extensions/DependencyInjection/ServiceCollectionRepositoryExtensions.cs @@ -31,14 +31,14 @@ namespace Microsoft.Extensions.DependencyInjection if (primaryKeyType != null) { - //IRepository + //IRepository var repositoryInterface = typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType); if (repositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) { services.TryAddTransient(repositoryInterface, repositoryImplementationType); } - //IQueryableRepository + //IQueryableRepository var queryableRepositoryInterface = typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType); if (queryableRepositoryInterface.GetTypeInfo().IsAssignableFrom(repositoryImplementationType)) { diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs index aaf4e1da9a..76407cf8a5 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/EntityDto.cs @@ -8,15 +8,15 @@ namespace Volo.Abp.Application.Dtos } } - public class EntityDto : EntityDto, IEntityDto + public class EntityDto : EntityDto, IEntityDto { /// /// Id of the entity. /// - public TPrimaryKey Id { get; set; } + public TKey Id { get; set; } /// - /// Creates a new object. + /// Creates a new object. /// public EntityDto() { @@ -24,10 +24,10 @@ namespace Volo.Abp.Application.Dtos } /// - /// Creates a new object. + /// Creates a new object. /// /// Id of the entity - public EntityDto(TPrimaryKey id) + public EntityDto(TKey id) { Id = id; } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs index 00e0f98cdb..1f774e50d1 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Dtos/IEntityDto.cs @@ -5,8 +5,8 @@ } - public interface IEntityDto : IEntityDto + public interface IEntityDto : IEntityDto { - TPrimaryKey Id { get; set; } + TKey Id { get; set; } } } \ No newline at end of file diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 2e631d2f4c..bbd4a8eaeb 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -7,59 +7,59 @@ using Volo.Abp.Linq; namespace Volo.Abp.Application.Services { - public abstract class AsyncCrudAppService - : AsyncCrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class AsyncCrudAppService + : AsyncCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected AsyncCrudAppService(IQueryableRepository repository) + protected AsyncCrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class AsyncCrudAppService - : AsyncCrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class AsyncCrudAppService + : AsyncCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected AsyncCrudAppService(IQueryableRepository repository) + protected AsyncCrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class AsyncCrudAppService - : AsyncCrudAppService + public abstract class AsyncCrudAppService + : AsyncCrudAppService where TGetAllInput : IPagedAndSortedResultRequest - where TEntity : class, IEntity - where TEntityDto : IEntityDto - where TCreateInput : IEntityDto + where TEntity : class, IEntity + where TEntityDto : IEntityDto + where TCreateInput : IEntityDto { - protected AsyncCrudAppService(IQueryableRepository repository) + protected AsyncCrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class AsyncCrudAppService - : CrudAppServiceBase, - IAsyncCrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class AsyncCrudAppService + : CrudAppServiceBase, + IAsyncCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } - protected AsyncCrudAppService(IQueryableRepository repository) + protected AsyncCrudAppService(IQueryableRepository repository) :base(repository) { AsyncQueryableExecuter = DefaultAsyncQueryableExecuter.Instance; } - public virtual async Task GetAsync(TPrimaryKey id) + public virtual async Task GetAsync(TKey id) { CheckGetPermission(); @@ -98,7 +98,7 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual async Task UpdateAsync(TPrimaryKey id, TUpdateInput input) + public virtual async Task UpdateAsync(TKey id, TUpdateInput input) { CheckUpdatePermission(); @@ -112,14 +112,14 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual Task DeleteAsync(TPrimaryKey id) + public virtual Task DeleteAsync(TKey id) { CheckDeletePermission(); return Repository.DeleteAsync(id); } - protected virtual Task GetEntityByIdAsync(TPrimaryKey id) + protected virtual Task GetEntityByIdAsync(TKey id) { return Repository.GetAsync(id); } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs index cec074f909..367552dba0 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppService.cs @@ -5,56 +5,56 @@ using Volo.Abp.Domain.Repositories; namespace Volo.Abp.Application.Services { - public abstract class CrudAppService - : CrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class CrudAppService + : CrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected CrudAppService(IQueryableRepository repository) + protected CrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class CrudAppService - : CrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class CrudAppService + : CrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected CrudAppService(IQueryableRepository repository) + protected CrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class CrudAppService - : CrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto - where TCreateInput : IEntityDto + public abstract class CrudAppService + : CrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + where TCreateInput : IEntityDto { - protected CrudAppService(IQueryableRepository repository) + protected CrudAppService(IQueryableRepository repository) : base(repository) { } } - public abstract class CrudAppService - : CrudAppServiceBase, - ICrudAppService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class CrudAppService + : CrudAppServiceBase, + ICrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected CrudAppService(IQueryableRepository repository) + protected CrudAppService(IQueryableRepository repository) : base(repository) { } - public virtual TEntityDto Get(TPrimaryKey id) + public virtual TEntityDto Get(TKey id) { CheckGetPermission(); @@ -93,7 +93,7 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual TEntityDto Update(TPrimaryKey id, TUpdateInput input) + public virtual TEntityDto Update(TKey id, TUpdateInput input) { CheckUpdatePermission(); @@ -105,14 +105,14 @@ namespace Volo.Abp.Application.Services return MapToEntityDto(entity); } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey id) { CheckDeletePermission(); Repository.Delete(id); } - protected virtual TEntity GetEntityById(TPrimaryKey id) + protected virtual TEntity GetEntityById(TKey id) { return Repository.Get(id); } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppServiceBase.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppServiceBase.cs index ec04a532ab..b9ad25a574 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/CrudAppServiceBase.cs +++ b/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. /// Inherit either from CrudAppService or AsyncCrudAppService, not from this class. /// - public abstract class CrudAppServiceBase : ApplicationService - where TEntity : class, IEntity - where TEntityDto : IEntityDto + public abstract class CrudAppServiceBase : ApplicationService + where TEntity : class, IEntity + where TEntityDto : IEntityDto { - protected IQueryableRepository Repository { get; } + protected IQueryableRepository Repository { get; } protected virtual string GetPermissionName { get; set; } @@ -27,7 +27,7 @@ namespace Volo.Abp.Application.Services protected virtual string DeletePermissionName { get; set; } - protected CrudAppServiceBase(IQueryableRepository repository) + protected CrudAppServiceBase(IQueryableRepository repository) { Repository = repository; } @@ -119,7 +119,7 @@ namespace Volo.Abp.Application.Services } /// - /// Sets Id value for the entity if is . + /// Sets Id value for the entity if is . /// It's used while creating a new entity. /// protected virtual void SetIdForGuids(TEntity entity) diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs index 37c8293df4..4f97c49ae0 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/IAsyncCrudAppService.cs @@ -3,39 +3,39 @@ using Volo.Abp.Application.Dtos; namespace Volo.Abp.Application.Services { - public interface IAsyncCrudAppService - : IAsyncCrudAppService - where TEntityDto : IEntityDto + public interface IAsyncCrudAppService + : IAsyncCrudAppService + where TEntityDto : IEntityDto { } - public interface IAsyncCrudAppService - : IAsyncCrudAppService - where TEntityDto : IEntityDto + public interface IAsyncCrudAppService + : IAsyncCrudAppService + where TEntityDto : IEntityDto { } - public interface IAsyncCrudAppService - : IAsyncCrudAppService - where TEntityDto : IEntityDto + public interface IAsyncCrudAppService + : IAsyncCrudAppService + where TEntityDto : IEntityDto { } - public interface IAsyncCrudAppService + public interface IAsyncCrudAppService : IApplicationService - where TEntityDto : IEntityDto + where TEntityDto : IEntityDto { - Task GetAsync(TPrimaryKey id); + Task GetAsync(TKey id); Task> GetListAsync(TGetListInput input); Task CreateAsync(TCreateInput input); - Task UpdateAsync(TPrimaryKey id, TUpdateInput input); + Task UpdateAsync(TKey id, TUpdateInput input); - Task DeleteAsync(TPrimaryKey id); + Task DeleteAsync(TKey id); } } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs index 9400f8825c..9f06c63aea 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Application/Services/ICrudAppService.cs @@ -2,39 +2,39 @@ using Volo.Abp.Application.Dtos; namespace Volo.Abp.Application.Services { - public interface ICrudAppService - : ICrudAppService - where TEntityDto : IEntityDto + public interface ICrudAppService + : ICrudAppService + where TEntityDto : IEntityDto { } - public interface ICrudAppService - : ICrudAppService - where TEntityDto : IEntityDto + public interface ICrudAppService + : ICrudAppService + where TEntityDto : IEntityDto { } - public interface ICrudAppService - : ICrudAppService - where TEntityDto : IEntityDto + public interface ICrudAppService + : ICrudAppService + where TEntityDto : IEntityDto { } - public interface ICrudAppService + public interface ICrudAppService : IApplicationService - where TEntityDto : IEntityDto + where TEntityDto : IEntityDto { - TEntityDto Get(TPrimaryKey id); + TEntityDto Get(TKey id); PagedResultDto GetAll(TGetListInput 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); } } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs b/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs index e195a348bf..917e9bd57a 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/CommonDbContextRegistrationOptions.cs +++ b/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 DefaultRepositoryImplementationTypeWithoutPrimaryKey { get; private set; } + public Type DefaultRepositoryImplementationTypeWithouTKey { get; private set; } public bool RegisterDefaultRepositories { get; private set; } @@ -27,7 +27,7 @@ namespace Volo.Abp.DependencyInjection public Dictionary CustomRepositories { get; } - public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithoutPrimaryKey != null; + public bool SpecifiedDefaultRepositoryTypes => DefaultRepositoryImplementationType != null && DefaultRepositoryImplementationTypeWithouTKey != null; protected CommonDbContextRegistrationOptions(Type originalDbContextType) { @@ -88,14 +88,14 @@ namespace Volo.Abp.DependencyInjection public ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses( Type repositoryImplementationType, - Type repositoryImplementationTypeWithoutPrimaryKey + Type repositoryImplementationTypeWithouTKey ) { Check.NotNull(repositoryImplementationType, nameof(repositoryImplementationType)); - Check.NotNull(repositoryImplementationTypeWithoutPrimaryKey, nameof(repositoryImplementationTypeWithoutPrimaryKey)); + Check.NotNull(repositoryImplementationTypeWithouTKey, nameof(repositoryImplementationTypeWithouTKey)); DefaultRepositoryImplementationType = repositoryImplementationType; - DefaultRepositoryImplementationTypeWithoutPrimaryKey = repositoryImplementationTypeWithoutPrimaryKey; + DefaultRepositoryImplementationTypeWithouTKey = repositoryImplementationTypeWithouTKey; return this; } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs b/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs index c68b544ce2..837f7bc110 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/DependencyInjection/ICommonDbContextRegistrationOptionsBuilder.cs @@ -48,9 +48,9 @@ namespace Volo.Abp.DependencyInjection /// Uses given class(es) for default repositories. /// /// Repository implementation type - /// Repository implementation type (without primary key) + /// Repository implementation type (without primary key) /// - ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType, [NotNull] Type repositoryImplementationTypeWithoutPrimaryKey); + ICommonDbContextRegistrationOptionsBuilder SetDefaultRepositoryClasses([NotNull] Type repositoryImplementationType, [NotNull] Type repositoryImplementationTypeWithouTKey); /// /// Replaces given DbContext type with this DbContext type. diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs index 65853729d6..a2b233406f 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/AggregateRoot.cs @@ -7,8 +7,8 @@ } - /// - public abstract class AggregateRoot : Entity, IAggregateRoot + /// + public abstract class AggregateRoot : Entity, IAggregateRoot { } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs index 185aad9767..007442f781 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/Entity.cs @@ -12,16 +12,16 @@ namespace Volo.Abp.Domain.Entities } } - /// - public abstract class Entity : Entity, IEntity + /// + public abstract class Entity : Entity, IEntity { /// - public virtual TPrimaryKey Id { get; set; } + public virtual TKey Id { get; set; } /// public override bool Equals(object obj) { - if (obj == null || !(obj is Entity)) + if (obj == null || !(obj is Entity)) { return false; } @@ -33,7 +33,7 @@ namespace Volo.Abp.Domain.Entities } //Transient objects are not considered as equal - var other = (Entity)obj; + var other = (Entity)obj; if (EntityHelper.IsTransient(this) && EntityHelper.IsTransient(other)) { return false; @@ -61,7 +61,7 @@ namespace Volo.Abp.Domain.Entities return Id.GetHashCode(); } - public static bool operator ==(Entity left, Entity right) + public static bool operator ==(Entity left, Entity right) { if (Equals(left, null)) { @@ -71,7 +71,7 @@ namespace Volo.Abp.Domain.Entities return left.Equals(right); } - public static bool operator !=(Entity left, Entity right) + public static bool operator !=(Entity left, Entity right) { return !(left == right); } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs index 3dee5b0ee5..18f6f2a8e9 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/EntityHelper.cs @@ -16,20 +16,20 @@ namespace Volo.Abp.Domain.Entities return typeof(IEntity).IsAssignableFrom(type); } - public static bool IsTransient(IEntity entity) // TODO: Completely remove IsTransient + public static bool IsTransient(IEntity entity) // TODO: Completely remove IsTransient { - if (EqualityComparer.Default.Equals(entity.Id, default)) + if (EqualityComparer.Default.Equals(entity.Id, default)) { return true; } //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; } - if (typeof(TPrimaryKey) == typeof(long)) + if (typeof(TKey) == typeof(long)) { return Convert.ToInt64(entity.Id) <= 0; } @@ -39,7 +39,7 @@ namespace Volo.Abp.Domain.Entities /// /// Tries to find the primary key type of the given entity type. - /// May return null if given type does not implement + /// May return null if given type does not implement /// [CanBeNull] public static Type FindPrimaryKeyType() @@ -50,7 +50,7 @@ namespace Volo.Abp.Domain.Entities /// /// Tries to find the primary key type of the given entity type. - /// May return null if given type does not implement + /// May return null if given type does not implement /// [CanBeNull] public static Type FindPrimaryKeyType([NotNull] Type entityType) @@ -71,13 +71,13 @@ namespace Volo.Abp.Domain.Entities return null; } - public static Expression> CreateEqualityExpressionForId(TPrimaryKey id) - where TEntity : IEntity + public static Expression> CreateEqualityExpressionForId(TKey id) + where TEntity : IEntity { var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaBody = Expression.Equal( Expression.PropertyOrField(lambdaParam, "Id"), - Expression.Constant(id, typeof(TPrimaryKey)) + Expression.Constant(id, typeof(TKey)) ); return Expression.Lambda>(lambdaBody, lambdaParam); diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs index 5050df0cca..bdb436c51d 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IAggregateRoot.cs @@ -2,7 +2,7 @@ { /// /// Defines an aggregate root. It's primary key may not be "Id" or it may have a composite primary key. - /// Use where possible for better integration to repositories and other structures in the framework. + /// Use where possible for better integration to repositories and other structures in the framework. /// public interface IAggregateRoot : IEntity { @@ -12,8 +12,8 @@ /// /// Defines an aggregate root with a single primary key with "Id" property. /// - /// Type of the primary key of the entity - public interface IAggregateRoot : IEntity, IAggregateRoot + /// Type of the primary key of the entity + public interface IAggregateRoot : IEntity, IAggregateRoot { } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs index a2f17e3f82..4cc25837d1 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Entities/IEntity.cs @@ -2,7 +2,7 @@ { /// /// Defines an entity. It's primary key may not be "Id" or it mah have a composite primary key. - /// Use where possible for better integration to repositories and other structures in the framework. + /// Use where possible for better integration to repositories and other structures in the framework. /// public interface IEntity { @@ -12,12 +12,12 @@ /// /// Defines an entity with a single primary key with "Id" property. /// - /// Type of the primary key of the entity - public interface IEntity : IEntity + /// Type of the primary key of the entity + public interface IEntity : IEntity { /// /// Unique identifier for this entity. /// - TPrimaryKey Id { get; set; } + TKey Id { get; set; } } } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs index 6a0e35e4ed..52014849ad 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IQueryableRepository.cs @@ -31,8 +31,8 @@ namespace Volo.Abp.Domain.Repositories Task DeleteAsync([NotNull] Expression> predicate, CancellationToken cancellationToken = default); } - public interface IQueryableRepository : IQueryableRepository, IRepository - where TEntity : class, IEntity + public interface IQueryableRepository : IQueryableRepository, IRepository + where TEntity : class, IEntity { } } \ No newline at end of file diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IRepository.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IRepository.cs index 1b70ff510f..94521c7628 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/IRepository.cs +++ b/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 } - public interface IRepository : IRepository - where TEntity : class, IEntity + public interface IRepository : IRepository + where TEntity : class, IEntity { /// /// Gets an entity with given primary key. @@ -79,7 +79,7 @@ namespace Volo.Abp.Domain.Repositories /// Primary key of the entity to get /// Entity [NotNull] - TEntity Get(TPrimaryKey id); + TEntity Get(TKey id); /// /// Gets an entity with given primary key. @@ -89,7 +89,7 @@ namespace Volo.Abp.Domain.Repositories /// A to observe while waiting for the task to complete. /// Entity [NotNull] - Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default); + Task GetAsync(TKey id, CancellationToken cancellationToken = default); /// /// Gets an entity with given primary key or null if not found. @@ -97,7 +97,7 @@ namespace Volo.Abp.Domain.Repositories /// Primary key of the entity to get /// Entity or null [CanBeNull] - TEntity Find(TPrimaryKey id); + TEntity Find(TKey id); /// /// Gets an entity with given primary key or null if not found. @@ -105,19 +105,19 @@ namespace Volo.Abp.Domain.Repositories /// Primary key of the entity to get /// A to observe while waiting for the task to complete. /// Entity or null - Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default); + Task FindAsync(TKey id, CancellationToken cancellationToken = default); /// /// Deletes an entity by primary key. /// /// Primary key of the entity - void Delete(TPrimaryKey id); //TODO: Return true if deleted + void Delete(TKey id); //TODO: Return true if deleted /// /// Deletes an entity by primary key. /// /// A to observe while waiting for the task to complete. /// Primary key of the entity - Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default); //TODO: Return true if deleted + Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); //TODO: Return true if deleted } } diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs index 9b4a98863c..79eb68daf6 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/ISupportsExplicitLoading.cs @@ -7,8 +7,8 @@ using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories { - public interface ISupportsExplicitLoading - where TEntity : class, IEntity + public interface ISupportsExplicitLoading + where TEntity : class, IEntity { Task EnsureCollectionLoadedAsync( TEntity entity, diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs index 00ef2c07be..f7000714e0 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs @@ -68,15 +68,15 @@ namespace Volo.Abp.Domain.Repositories } } - public abstract class QueryableRepositoryBase : QueryableRepositoryBase, IQueryableRepository - where TEntity : class, IEntity + public abstract class QueryableRepositoryBase : QueryableRepositoryBase, IQueryableRepository + where TEntity : class, IEntity { - public virtual TEntity Find(TPrimaryKey id) + public virtual TEntity Find(TKey id) { - return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id)); + return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id)); } - public virtual TEntity Get(TPrimaryKey id) + public virtual TEntity Get(TKey id) { var entity = Find(id); @@ -88,17 +88,17 @@ namespace Volo.Abp.Domain.Repositories return entity; } - public virtual Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task GetAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Get(id)); } - public virtual Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task FindAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Find(id)); } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey id) { var entity = Find(id); if (entity == null) @@ -109,7 +109,7 @@ namespace Volo.Abp.Domain.Repositories Delete(entity); } - public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) { Delete(id); return Task.CompletedTask; diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs index bc52a145a8..953b967c2c 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryBase.cs @@ -43,10 +43,10 @@ namespace Volo.Abp.Domain.Repositories } } - public abstract class RepositoryBase : RepositoryBase, IRepository - where TEntity : class, IEntity + public abstract class RepositoryBase : RepositoryBase, IRepository + where TEntity : class, IEntity { - public virtual TEntity Get(TPrimaryKey id) + public virtual TEntity Get(TKey id) { var entity = Find(id); @@ -58,19 +58,19 @@ namespace Volo.Abp.Domain.Repositories return entity; } - public virtual Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task GetAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Get(id)); } - public abstract TEntity Find(TPrimaryKey id); + public abstract TEntity Find(TKey id); - public virtual Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task FindAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Find(id)); } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey id) { var entity = Find(id); if (entity == null) @@ -81,7 +81,7 @@ namespace Volo.Abp.Domain.Repositories Delete(entity); } - public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) { Delete(id); return Task.CompletedTask; diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs index 3c9a503780..ccb4cd2c60 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryExtensions.cs +++ b/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 async Task EnsureCollectionLoadedAsync( - this IRepository repository, + public static async Task EnsureCollectionLoadedAsync( + this IRepository repository, TEntity entity, Expression>> propertyExpression, CancellationToken cancellationToken = default ) - where TEntity : class, IEntity + where TEntity : class, IEntity where TProperty : class { - var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading; + var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading; if (repo != null) { await repo.EnsureCollectionLoadedAsync(entity, propertyExpression, cancellationToken); } } - public static void EnsureCollectionLoaded( - this IRepository repository, + public static void EnsureCollectionLoaded( + this IRepository repository, TEntity entity, Expression>> propertyExpression ) - where TEntity : class, IEntity + where TEntity : class, IEntity where TProperty : class { AsyncHelper.RunSync(() => repository.EnsureCollectionLoadedAsync(entity, propertyExpression)); } - public static async Task EnsurePropertyLoadedAsync( - this IRepository repository, + public static async Task EnsurePropertyLoadedAsync( + this IRepository repository, TEntity entity, Expression> propertyExpression, CancellationToken cancellationToken = default ) - where TEntity : class, IEntity + where TEntity : class, IEntity where TProperty : class { - var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading; + var repo = ProxyHelper.UnProxy(repository) as ISupportsExplicitLoading; if (repo != null) { await repo.EnsurePropertyLoadedAsync(entity, propertyExpression, cancellationToken); } } - public static void EnsurePropertyLoaded( - this IRepository repository, + public static void EnsurePropertyLoaded( + this IRepository repository, TEntity entity, Expression> propertyExpression ) - where TEntity : class, IEntity + where TEntity : class, IEntity where TProperty : class { AsyncHelper.RunSync(() => repository.EnsurePropertyLoadedAsync(entity, propertyExpression)); diff --git a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs index 9b5510de89..addae8de35 100644 --- a/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs +++ b/src/Volo.Abp.Ddd/Volo/Abp/Domain/Repositories/RepositoryRegistrarBase.cs @@ -57,7 +57,7 @@ namespace Volo.Abp.Domain.Repositories if (primaryKeyType == null) { return Options.SpecifiedDefaultRepositoryTypes - ? Options.DefaultRepositoryImplementationTypeWithoutPrimaryKey.MakeGenericType(entityType) + ? Options.DefaultRepositoryImplementationTypeWithouTKey.MakeGenericType(entityType) : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType); } diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs index 84471504f7..33f34a79bf 100644 --- a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EfCoreRepositoryExtensions.cs +++ b/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 DbContext GetDbContext(this IRepository repository) - where TEntity : class, IEntity + public static DbContext GetDbContext(this IRepository repository) + where TEntity : class, IEntity { return repository.ToEfCoreRepository().DbContext; } - public static DbSet GetDbSet(this IRepository repository) - where TEntity : class, IEntity + public static DbSet GetDbSet(this IRepository repository) + where TEntity : class, IEntity { return repository.ToEfCoreRepository().DbSet; } - public static IEfCoreRepository ToEfCoreRepository(this IRepository repository) - where TEntity : class, IEntity + public static IEfCoreRepository ToEfCoreRepository(this IRepository repository) + where TEntity : class, IEntity { - var efCoreRepository = repository as IEfCoreRepository; + var efCoreRepository = repository as IEfCoreRepository; if (efCoreRepository == null) { - throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository).AssemblyQualifiedName, nameof(repository)); + throw new ArgumentException("Given repository does not implement " + typeof(IEfCoreRepository).AssemblyQualifiedName, nameof(repository)); } return efCoreRepository; diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs index 9bd7245b7a..322096084d 100644 --- a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs +++ b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -95,12 +95,12 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore } } - public class EfCoreRepository : EfCoreRepository, - IEfCoreRepository, - ISupportsExplicitLoading + public class EfCoreRepository : EfCoreRepository, + IEfCoreRepository, + ISupportsExplicitLoading where TDbContext : IEfCoreDbContext - where TEntity : class, IEntity + where TEntity : class, IEntity { public EfCoreRepository(IDbContextProvider 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); @@ -120,7 +120,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return entity; } - public virtual async Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(TKey id, CancellationToken cancellationToken = default) { var entity = await FindAsync(id, GetCancellationToken(cancellationToken)); @@ -132,17 +132,17 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore return entity; } - public virtual TEntity Find(TPrimaryKey id) + public virtual TEntity Find(TKey id) { return DbSet.Find(id); } - public virtual Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task FindAsync(TKey id, CancellationToken cancellationToken = default) { return DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken)); } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey id) { var entity = Find(id); if (entity == null) @@ -153,7 +153,7 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore Delete(entity); } - public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) { Delete(id); return Task.CompletedTask; diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs index 8232f02fcd..b0354df4c9 100644 --- a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs +++ b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs @@ -11,8 +11,8 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore DbSet DbSet { get; } } - public interface IEfCoreRepository : IEfCoreRepository, IQueryableRepository - where TEntity : class, IEntity + public interface IEfCoreRepository : IEfCoreRepository, IQueryableRepository + where TEntity : class, IEntity { } diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs index 7cbaf15e70..1e6cd6f54c 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs +++ b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDatabase.cs @@ -6,6 +6,6 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb { List Collection(); - TPrimaryKey GenerateNextId(); + TKey GenerateNextId(); } } \ No newline at end of file diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs index 8d43180088..6b89208130 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs +++ b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/IMemoryDbRepository.cs @@ -11,8 +11,8 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb List Collection { get; } } - public interface IMemoryDbRepository : IMemoryDbRepository, IQueryableRepository - where TEntity : class, IEntity + public interface IMemoryDbRepository : IMemoryDbRepository, IQueryableRepository + where TEntity : class, IEntity { } diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/InMemoryIdGenerator.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/InMemoryIdGenerator.cs index 1741d2cc02..467fff5bc5 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/InMemoryIdGenerator.cs +++ b/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 long _lastLong; - public TPrimaryKey GenerateNext() + public TKey GenerateNext() { - 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); } } } \ No newline at end of file diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs index 332138eae2..212c151087 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDatabase.cs +++ b/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()) as List; } - public TPrimaryKey GenerateNextId() + public TKey GenerateNextId() { return _idGenerators .GetOrAdd(typeof(TEntity), () => new InMemoryIdGenerator()) - .GenerateNext(); + .GenerateNext(); } } } \ No newline at end of file diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index acd37028a4..72e84d126f 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -45,9 +45,9 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb } } - public class MemoryDbRepository : MemoryDbRepository, IMemoryDbRepository + public class MemoryDbRepository : MemoryDbRepository, IMemoryDbRepository where TMemoryDbContext : MemoryDbContext - where TEntity : class, IEntity + where TEntity : class, IEntity { public MemoryDbRepository(IMemoryDatabaseProvider databaseProvider) : base(databaseProvider) @@ -62,21 +62,21 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb 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)) { - entity.Id = Database.GenerateNextId(); + entity.Id = Database.GenerateNextId(); } } } - public virtual TEntity Find(TPrimaryKey id) + public virtual TEntity Find(TKey id) { - return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id)); + return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id)); } - public virtual TEntity Get(TPrimaryKey id) + public virtual TEntity Get(TKey id) { var entity = Find(id); @@ -88,17 +88,17 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb return entity; } - public virtual Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task GetAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Get(id)); } - public virtual Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task FindAsync(TKey id, CancellationToken cancellationToken = default) { return Task.FromResult(Find(id)); } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey id) { var entity = Find(id); if (entity == null) @@ -109,7 +109,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb Delete(entity); } - public virtual Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) { Delete(id); return Task.CompletedTask; diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs index 71192d03ed..4071646c7d 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDbCoreRepositoryExtensions.cs +++ b/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 IMemoryDatabase GetDatabase(this IRepository repository) - where TEntity : class, IEntity + public static IMemoryDatabase GetDatabase(this IRepository repository) + where TEntity : class, IEntity { return repository.ToMemoryDbRepository().Database; } - public static List GetCollection(this IRepository repository) - where TEntity : class, IEntity + public static List GetCollection(this IRepository repository) + where TEntity : class, IEntity { return repository.ToMemoryDbRepository().Collection; } - public static IMemoryDbRepository ToMemoryDbRepository(this IRepository repository) - where TEntity : class, IEntity + public static IMemoryDbRepository ToMemoryDbRepository(this IRepository repository) + where TEntity : class, IEntity { - var memoryDbRepository = repository as IMemoryDbRepository; + var memoryDbRepository = repository as IMemoryDbRepository; if (memoryDbRepository == null) { - throw new ArgumentException("Given repository does not implement " + typeof(IMemoryDbRepository).AssemblyQualifiedName, nameof(repository)); + throw new ArgumentException("Given repository does not implement " + typeof(IMemoryDbRepository).AssemblyQualifiedName, nameof(repository)); } return memoryDbRepository; diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs index c20c5dca1e..c8f5eb0265 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs @@ -13,8 +13,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB string CollectionName { get; } } - public interface IMongoDbRepository : IMongoDbRepository, IQueryableRepository - where TEntity : class, IEntity + public interface IMongoDbRepository : IMongoDbRepository, IQueryableRepository + where TEntity : class, IEntity { } diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 3141da949e..348ed9e957 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -81,9 +81,9 @@ namespace Volo.Abp.Domain.Repositories.MongoDB } } - public class MongoDbRepository : MongoDbRepository, IMongoDbRepository + public class MongoDbRepository : MongoDbRepository, IMongoDbRepository where TMongoDbContext : AbpMongoDbContext - where TEntity : class, IEntity + where TEntity : class, IEntity { public MongoDbRepository(IMongoDatabaseProvider 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); @@ -103,7 +103,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB return entity; } - public virtual async Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(TKey id, CancellationToken cancellationToken = default) { var entity = await FindAsync(id, cancellationToken); @@ -115,22 +115,22 @@ namespace Volo.Abp.Domain.Repositories.MongoDB return entity; } - public virtual void Delete(TPrimaryKey id) + public virtual void Delete(TKey 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); } - public virtual async Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public virtual async Task FindAsync(TKey id, CancellationToken cancellationToken = default) { 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(); } @@ -140,7 +140,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB return Builders.Filter.Eq(e => e.Id, entity.Id); } - private static FilterDefinition CreateEntityFilter(TPrimaryKey id) + private static FilterDefinition CreateEntityFilter(TKey id) { return Builders.Filter.Eq(e => e.Id, id); } diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs index b553637002..dba22e8e1b 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs +++ b/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 IMongoDatabase GetDatabase(this IRepository repository) - where TEntity : class, IEntity + public static IMongoDatabase GetDatabase(this IRepository repository) + where TEntity : class, IEntity { return repository.ToMongoDbRepository().Database; } - public static IMongoCollection GetCollection(this IRepository repository) - where TEntity : class, IEntity + public static IMongoCollection GetCollection(this IRepository repository) + where TEntity : class, IEntity { return repository.ToMongoDbRepository().Collection; } - public static string GetCollectionName(this IRepository repository) - where TEntity : class, IEntity + public static string GetCollectionName(this IRepository repository) + where TEntity : class, IEntity { return repository.ToMongoDbRepository().CollectionName; } - public static IMongoDbRepository ToMongoDbRepository(this IRepository repository) - where TEntity : class, IEntity + public static IMongoDbRepository ToMongoDbRepository(this IRepository repository) + where TEntity : class, IEntity { - var mongoDbRepository = repository as IMongoDbRepository; + var mongoDbRepository = repository as IMongoDbRepository; if (mongoDbRepository == null) { - throw new ArgumentException("Given repository does not implement " + typeof(IMongoDbRepository).AssemblyQualifiedName, nameof(repository)); + throw new ArgumentException("Given repository does not implement " + typeof(IMongoDbRepository).AssemblyQualifiedName, nameof(repository)); } return mongoDbRepository; diff --git a/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs b/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs index 372f3fb6b9..5f082eb52a 100644 --- a/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs +++ b/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs @@ -169,35 +169,35 @@ namespace Volo.Abp.Domain.Repositories } } - public class MyTestDefaultRepository : MyTestDefaultRepository, IRepository - where TEntity : class, IEntity + public class MyTestDefaultRepository : MyTestDefaultRepository, IRepository + where TEntity : class, IEntity { - public TEntity Get(TPrimaryKey id) + public TEntity Get(TKey id) { throw new NotImplementedException(); } - public Task GetAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public Task GetAsync(TKey id, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TEntity Find(TPrimaryKey id) + public TEntity Find(TKey id) { throw new NotImplementedException(); } - public Task FindAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public Task FindAsync(TKey id, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public void Delete(TPrimaryKey id) + public void Delete(TKey id) { throw new NotImplementedException(); } - public Task DeleteAsync(TPrimaryKey id, CancellationToken cancellationToken = default) + public Task DeleteAsync(TKey id, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -214,8 +214,8 @@ namespace Volo.Abp.Domain.Repositories } - public class MyTestCustomBaseRepository : MyTestDefaultRepository - where TEntity : class, IEntity + public class MyTestCustomBaseRepository : MyTestDefaultRepository + where TEntity : class, IEntity { } diff --git a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs index 45f31c705b..142e97463e 100644 --- a/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs +++ b/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using Volo.Abp.Domain.Entities; namespace Volo.Abp.TestApp.Domain @@ -25,4 +27,74 @@ namespace Volo.Abp.TestApp.Domain Type = type; } } + + public class Order : AggregateRoot + { + public virtual string ReferenceNo { get; protected set; } + + public virtual float TotalItemCount { get; protected set; } + + public virtual DateTime CreationTime { get; protected set; } + + public virtual List OrderLines { get; protected set; } + + protected Order() + { + + } + + public Order(Guid id, string referenceNo) + { + Id = id; + ReferenceNo = referenceNo; + OrderLines = new List(); + } + + 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; + } + } } \ No newline at end of file