Create Command
The EntityCreateCommand<TCreateModel, TReadModel>
represents a command to create a new entity using the specified create model. This command follows the CQRS (Command Query Responsibility Segregation) pattern and returns a read model representing the created entity.
Overview
The create command is a fundamental part of the Arbiter framework's CRUD operations. It inherits from EntityModelCommand<TCreateModel, TReadModel>
which provides automatic security context, audit tracking, and JSON serialization support.
public record EntityCreateCommand<TCreateModel, TReadModel>
: EntityModelCommand<TCreateModel, TReadModel>, ICacheExpire
Key Features
- Security Context: Built-in
ClaimsPrincipal
support for authentication and authorization - Audit Tracking: Automatic creation metadata tracking including
Created
,CreatedBy
,Updated
, andUpdatedBy
fields - Cache Integration: Implements
ICacheExpire
for automatic cache invalidation - Validation: Integrated with validation pipeline behaviors
- Mapping: Uses Mapper for converting between create models and entities
- Tenant Support: Optional multi-tenant support through
IHaveTenant<TKey>
interface
Type Parameters
Parameter | Description |
---|---|
TCreateModel |
The type of the create model containing the data for the new entity |
TReadModel |
The type of the read model returned as the result of the command |
Constructor Parameters
Parameter | Type | Description |
---|---|---|
principal |
ClaimsPrincipal? |
The user's security context. Used for audit tracking and authorization |
model |
TCreateModel |
The create model containing the data for the new entity |
Automatic Metadata Tracking
When an entity implements tracking interfaces, the command automatically populates metadata:
ITrackCreated
: SetsCreated
timestamp andCreatedBy
user identifierITrackUpdated
: SetsUpdated
timestamp andUpdatedBy
user identifier
Handler Implementations
The Arbiter framework provides built-in handlers for different data access patterns:
Entity Framework Handler
EntityCreateCommandHandler<TContext, TEntity, TKey, TCreateModel, TReadModel>
MongoDB Handler
EntityCreateCommandHandler<TRepository, TEntity, TKey, TCreateModel, TReadModel>
Service Registration
Register create command support using the provided extension methods:
Entity Framework
services.AddEntityCommands<MyDbContext, Product, int, ProductReadModel, ProductCreateModel, ProductUpdateModel>();
// Or register create command individually
services.AddEntityCreateCommand<MyDbContext, Product, int, ProductCreateModel, ProductReadModel>();
MongoDB
services.AddEntityCommands<IProductRepository, Product, int, ProductReadModel, ProductCreateModel, ProductUpdateModel>();
// Or register create command individually
services.AddEntityCreateCommand<IProductRepository, Product, int, ProductCreateModel, ProductReadModel>();
Model Mapping with IMapper
The create command relies on IMapper<TSource, TDestination>
to convert between different model types during the entity creation process. The framework uses two key mapping operations:
CreateModel to Entity Mapping
The command handler uses IMapper<TCreateModel, TEntity>
to convert the incoming create model into an entity that can be persisted to the database:
var entity = Mapper.Map<TCreateModel, TEntity>(request.Model);
Entity to ReadModel Mapping
After the entity is created and saved, IMapper<TEntity, TReadModel>
converts the persisted entity into a read model for the response:
return Mapper.Map<TEntity, TReadModel>(entity);
Pipeline Behaviors
The create command automatically includes several pipeline behaviors that execute in the pipeline:
Tenant Security:
TenantDefaultCommandBehavior
andTenantAuthenticateCommandBehavior
(if entity implementsIHaveTenant<TKey>
)TenantDefaultCommandBehavior
: Automatically sets the tenant ID from the current user's claims when not explicitly providedTenantAuthenticateCommandBehavior
: Validates that the user has access to the specified tenant and ensures tenant isolation
Change Tracking:
TrackChangeCommandBehavior
(if entity implements tracking interfaces)- Automatically populates audit fields like
Created
,CreatedBy
,Updated
, andUpdatedBy
based on the current user and timestamp
- Automatically populates audit fields like
Validation:
ValidateEntityModelCommandBehavior
- Performs model validation using data annotations or FluentValidation rules defined on the create model
- Throws validation exceptions if the model is invalid, which are automatically converted to HTTP 400 responses in web applications
Notifications:
EntityChangeNotificationBehavior
- Publishes domain events or notifications when entities are created, allowing other parts of the system to react to changes
- Useful for implementing event-driven architectures and cross-cutting concerns like logging or cache invalidation
Usage Examples
Basic Usage
var createModel = new ProductCreateModel
{
Name = "New Product",
Description = "A description of the new product",
Price = 19.99m
};
var principal = new ClaimsPrincipal(new ClaimsIdentity([new(ClaimTypes.Name, "JohnDoe")]));
var command = new EntityCreateCommand<ProductCreateModel, ProductReadModel>(principal, createModel);
var result = await mediator.Send(command);
Console.WriteLine($"Created product: {result?.Name}");
In ASP.NET Core Controller
[HttpPost]
public async Task<ProductReadModel?> CreateProduct([FromBody] ProductCreateModel createModel)
{
var command = new EntityCreateCommand<ProductCreateModel, ProductReadModel>(User, createModel);
return await mediator.Send(command);
}
In Minimal API Endpoint
app.MapPost("/products", async (
[FromServices] IMediator mediator,
[FromBody] ProductCreateModel createModel,
ClaimsPrincipal user) =>
{
var command = new EntityCreateCommand<ProductCreateModel, ProductReadModel>(user, createModel);
var result = await mediator.Send(command);
return Results.Ok(result);
});
Return Values
- Success: Returns the
TReadModel
representing the created entity - Exception: Throws appropriate exceptions for validation or data access errors
Error Handling
The command handlers include built-in error handling and will throw appropriate exceptions:
ArgumentNullException
: When the model parameter is nullDomainException
: For business rule violations- Database exceptions: For data access errors
Best Practices
- Model Validation: Implement data annotations or FluentValidation on your create models
- Mapping Configuration: Configure Mapper for
TCreateModel
toTEntity
mapping - Security: Always pass the current user's
ClaimsPrincipal
for proper audit tracking - Null Handling: The command constructor validates that the model is not null
- Cache Tags: The framework automatically manages cache invalidation based on entity types
- Authorization: Implement appropriate authorization checks in your application layer