Franz.Common.Business
1.5.3
dotnet add package Franz.Common.Business --version 1.5.3
NuGet\Install-Package Franz.Common.Business -Version 1.5.3
<PackageReference Include="Franz.Common.Business" Version="1.5.3" />
<PackageVersion Include="Franz.Common.Business" Version="1.5.3" />
<PackageReference Include="Franz.Common.Business" />
paket add Franz.Common.Business --version 1.5.3
#r "nuget: Franz.Common.Business, 1.5.3"
#:package Franz.Common.Business@1.5.3
#addin nuget:?package=Franz.Common.Business&version=1.5.3
#tool nuget:?package=Franz.Common.Business&version=1.5.3
Franz.Common.Business
A core library of the Franz Framework, designed to facilitate Domain-Driven Design (DDD) and CQRS (Command Query Responsibility Segregation) in .NET applications. It provides abstractions, utilities, and patterns for building scalable, maintainable, and testable business logic.
- Current Version: 1.5.3
Features
1. Domain-Driven Design (DDD) Building Blocks
- Entities: Represent unique objects identified by a primary key, with auditing + soft delete built-in.
- Value Objects: Immutable, equality-driven domain concepts.
- Enumerations: Strongly typed enums with behavior and metadata.
- Repositories: Interfaces for persistence (
IAggregateRepository<TAggregateRoot>
,IReadRepository<T>
).
Entity Example:
public class Order : Entity<Guid>
{
public string CustomerName { get; private set; }
public decimal TotalAmount { get; private set; }
public Order(Guid orderId, string customerName, decimal totalAmount)
{
Id = orderId;
CustomerName = customerName;
TotalAmount = totalAmount;
}
}
Value Object Example:
public class Address : ValueObject
{
public string Street { get; }
public string City { get; }
public string PostalCode { get; }
public Address(string street, string city, string postalCode)
{
Street = street;
City = city;
PostalCode = postalCode;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return PostalCode;
}
}
2. Aggregates (Event-Sourced)
🆕 Since 1.2.65, aggregates follow a strict event-driven model:
- Enforce consistency across related entities.
- State is modified only through events.
- Support replay via event sourcing.
- Always identified by
Guid
.
Example:
public class Product : EventSourcedAggregateRoot<ProductEvent>
{
public string Name { get; private set; }
public decimal Price { get; private set; }
private readonly List<ProductReview> _reviews = new();
public IReadOnlyCollection<ProductReview> Reviews => _reviews.AsReadOnly();
public Product(Guid id, string name, decimal price) : base(id)
{
RaiseEvent(new ProductCreatedEvent(id, name, price));
}
public void UpdatePrice(decimal newPrice)
{
if (newPrice <= 0) throw new InvalidOperationException("Price must be positive.");
RaiseEvent(new ProductPriceUpdatedEvent(Id, newPrice));
}
public void AddReview(string comment, int rating)
{
if (rating < 1 || rating > 5) throw new InvalidOperationException("Rating must be between 1 and 5.");
RaiseEvent(new ProductReviewAddedEvent(Id, comment, rating));
}
public void Apply(ProductCreatedEvent @event) { Id = @event.ProductId; Name = @event.Name; Price = @event.Price; }
public void Apply(ProductPriceUpdatedEvent @event) { Price = @event.NewPrice; }
public void Apply(ProductReviewAddedEvent @event) { _reviews.Add(new ProductReview(@event.Comment, @event.Rating)); }
}
3. Events
Supports both domain events and integration events.
IEvent
IEventHandler<TEvent>
IntegrationEvent
BaseEvent
Example:
public class OrderCreatedEvent : IEvent
{
public Guid OrderId { get; set; }
public string CustomerName { get; set; }
}
public class OrderCreatedHandler : IEventHandler<OrderCreatedEvent>
{
public async Task Handle(OrderCreatedEvent @event, CancellationToken cancellationToken)
{
Console.WriteLine($"Order created for {@event.CustomerName}.");
}
}
4. CQRS Support
- Commands (
ICommandRequest<T>
,ICommandHandler<TCommand,TResponse>
) - Queries (
IQueryRequest<T>
,IQueryHandler<TQuery,TResponse>
)
Command Example:
public class CreateOrderCommand : ICommandRequest<Guid>
{
public string CustomerName { get; set; }
public decimal TotalAmount { get; set; }
}
public class CreateOrderHandler : ICommandHandler<CreateOrderCommand, Guid>
{
public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
var orderId = Guid.NewGuid();
Console.WriteLine($"Order created for {request.CustomerName} with ID: {orderId}");
return orderId;
}
}
5. Registration Examples
The Business layer integrates seamlessly with the Mediator and resilience pipelines.
a) AddBusinessWithMediator
Strict registration – will throw if your *.Application
assembly is not found.
builder.Services.AddBusinessWithMediator(typeof(Program).Assembly);
b) TryAddBusinessWithMediator
Soft registration – logs a warning but continues if the application assembly is missing.
builder.Services.TryAddBusinessWithMediator(typeof(Program).Assembly);
c) AddFranzPlatform
Full-stack registration – Business + Mediator + Logging + Resilience pipelines.
builder.Services.AddFranzPlatform(
typeof(Program).Assembly,
options =>
{
options.DefaultTimeout = TimeSpan.FromSeconds(30);
});
6. Resilience Pipelines (via Mediator)
When you call AddFranzPlatform
, Franz.Common.Business
wires up the following Mediator pipelines:
- ✅
RetryPipeline<TRequest, TResponse>
- ✅
CircuitBreakerPipeline<TRequest, TResponse>
- ✅
TimeoutPipeline<TRequest, TResponse>
- ✅
BulkheadPipeline<TRequest, TResponse>
These are implemented in
Franz.Common.Mediator.Pipelines.Resilience
.Franz.Common.Business
just activates them for you.
7. appsettings.json Configuration
Each pipeline reads its Options from configuration:
{
"Franz": {
"Resilience": {
"Retry": {
"Enabled": true,
"RetryCount": 3,
"BaseDelayMilliseconds": 200
},
"CircuitBreaker": {
"Enabled": true,
"FailureThreshold": 5,
"OpenDurationSeconds": 60
},
"Timeout": {
"Enabled": true,
"TimeoutSeconds": 15
},
"Bulkhead": {
"Enabled": true,
"MaxParallelization": 50,
"MaxQueuingActions": 100
}
}
}
}
8. Options Mapping
Retry
→RetryOptions
CircuitBreaker
→CircuitBreakerOptions
Timeout
→TimeoutOptions
Bulkhead
→BulkheadOptions
9. Logging
On startup you’ll see log messages confirming bootstrap:
[INF] ✅ Franz.Business bootstrapped with MyProduct.Application, Version=1.0.0.0
[INF] 🛡️ Resilience pipelines registered: Retry, CircuitBreaker, Timeout, Bulkhead
[WRN] ⚠️ No Application assembly found for MyProduct.Application, Business layer not registered.
What’s New in 1.4.2
- 🗑️ Removed
SaveEntitiesAsync
→ all auditing + domain event dispatching happens inSaveChangesAsync
. - ✅ Aligned with DbContextBase from
Franz.Common.EntityFramework
. - 🧹 Internal cleanup and consistency improvements.
Dependencies
- Scrutor (4.2.2) – assembly scanning & DI.
- Microsoft.Extensions.DependencyInjection (9.0.0) – DI support.
- Franz.Common.Mediator – CQRS + pipelines.
- Franz.Common.Errors – standardized error handling.
Installation
dotnet add package Franz.Common.Business --version 1.4.2
⚠️ Since 1.4.1, MediatR is no longer required. Uses Franz.Common.Mediator internally.
Contributing
This package is part of the private Franz Framework.
- Clone repo.
- Create a feature branch.
- Submit a PR for review.
License
Licensed under the MIT License.
Changelog
Got it ✅ — let’s package those changes into a README-style changelog log so you can drop it straight into the repo alongside the code.
Here’s a draft for Franz.Common.Business v1.4.5
:
Franz.Common.Business — Release Notes
Version 1.4.5
A maintenance release focusing on consistency and event publishability.
🔹 Changes
AggregateRoot<TEvent>
Enforced publishable events by constraining
where TEvent : BaseDomainEvent, INotification
Ensures all domain events can be published via the Mediator pipeline.
Updated
GetUncommittedChanges()
signature:public IReadOnlyCollection<BaseDomainEvent> GetUncommittedChanges()
- Previously returned
IEnumerable<TEvent>
. - Now returns an immutable, standardized collection of
BaseDomainEvent
.
- Previously returned
IAggregateRoot
Updated contract for
GetUncommittedChanges()
:IReadOnlyCollection<BaseDomainEvent> GetUncommittedChanges();
Guarantees consistency with
AggregateRoot
.Retains:
void MarkChangesAsCommitted();
Guid Id { get; }
✅ Benefits
- Consistency across AggregateRoot and IAggregateRoot.
- Safety via
IReadOnlyCollection
(prevents external mutation). - Alignment with MediatR’s
INotification
pattern, enforcing correct event semantics.
1.4.2
- Removed
SaveEntitiesAsync
→ replaced withSaveChangesAsync
inDbContextBase
. - Improved alignment with
EntityFramework
package (auditing + domain events).
1.4.1
- Independent from MediatR → runs on
Franz.Common.Mediator
. - Lifecycle tracking for entities & aggregates.
- Stronger value object equality.
- Enriched domain events with metadata.
- Scrutor-powered DI auto-discovery.
Got it ✅ — let’s make individual README entries for each package you’ve patched in v1.4.5
.
You’ll be able to drop these into each project’s README (under a Release Notes or Changelog section).
📌 Franz.Common.Business
v1.4.5
Consistency and publishability improvements for AggregateRoots.
- Enforced publishable events by requiring
TEvent : BaseDomainEvent, INotification
. - Updated
GetUncommittedChanges()
to returnIReadOnlyCollection<BaseDomainEvent>
instead ofIEnumerable<TEvent>
. - Updated
IAggregateRoot
contract for consistency withAggregateRoot
. - Improved safety (read-only collections) and alignment with MediatR’s
INotification
pattern.
📌 Franz.Common.EntityFramework
v1.4.5
Fixed event dispatch semantics for domain persistence.
- Replaced
dispatcher.Send(...)
withdispatcher.PublishAsync(...)
when dispatching domain events. - Applied fix to both standard and cancellation-token aware variants.
- Ensures domain events behave as fan-out notifications instead of commands.
📌 Franz.Common.Mediator
v1.4.5
Corrected mediator semantics for commands, queries, and events.
Introduced clear split:
- Commands/Queries →
SendAsync
(single handler, request/response). - Events (Domain + Integration) →
PublishAsync
(fan-out, fire-and-forget).
- Commands/Queries →
Fixed mis-implementation where integration events were incorrectly treated as commands.
Ensures consistent message handling semantics across the framework.
📌 Franz.Common.Messaging.Hosting.Mediator
v1.4.5
Fixed event dispatch handling in hosting layer.
IIntegrationEvent
now dispatched viaPublishAsync(...)
instead ofSend(...)
.- Commands and queries remain dispatched via
SendAsync(...)
. - Aligns hosting mediator with proper notification semantics.
📌 Franz.Common.Messaging.Kafka
v1.4.5
Corrected Kafka integration event pipeline.
- Changed mediator dispatch from
Send(message)
toPublishAsync(message)
. - Ensures Kafka-published integration events follow publish/notify semantics instead of command semantics.
- Provides consistent event behavior across transports.
⚡ That way, each project’s README stays self-contained and explains the exact scope of what changed in 1.4.5
.
Do you also want me to generate a root-level consolidated CHANGELOG.md
that includes all of these in one place (for repo-wide documentation)?
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Franz.Common.DependencyInjection (>= 1.5.3)
- Franz.Common.Errors (>= 1.5.3)
- Franz.Common.Mediator (>= 1.5.3)
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.8)
- Scrutor (>= 6.1.0)
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Franz.Common.Business:
Package | Downloads |
---|---|
Franz.Common.EntityFramework
Shared utility library for the Franz Framework. |
|
Franz.Common.Messaging
Shared utility library for the Franz Framework. |
|
Franz.Common.Serialization
Shared utility library for the Franz Framework. |
|
Franz.Common.Bootstrap
Shared utility library for the Franz Framework. |
|
Franz.Common.Http.Documentation
Shared utility library for the Franz Framework. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.5.3 | 0 | 9/21/2025 |
1.5.2 | 0 | 9/21/2025 |
1.5.0 | 0 | 9/21/2025 |
1.4.4 | 73 | 9/20/2025 |
1.3.14 | 244 | 9/18/2025 |
1.3.13 | 235 | 9/18/2025 |
1.3.5 | 267 | 9/17/2025 |
1.3.4 | 297 | 9/16/2025 |
1.3.3 | 305 | 9/16/2025 |
1.3.2 | 304 | 9/15/2025 |
1.3.1 | 124 | 9/12/2025 |
1.3.0 | 329 | 8/25/2025 |
1.2.65 | 280 | 3/3/2025 |
1.2.64 | 221 | 1/29/2025 |
1.2.63 | 263 | 1/27/2025 |
1.2.62 | 272 | 1/8/2025 |