Asset Value-Object Conversions
Summary
Source-backed inventory of the four value objects owned by the Asset aggregate and persisted as scalar columns on the Assets table — their domain purpose, stored columns, validation, structural equality, and query/index implications — plus the computed members that are never persisted.
Audience
Backend engineers, database reviewers, architects, QA, support, operations, security reviewers, and product owners.
Overview
The Asset aggregate models four concepts as value objects: AssetCode, AssetName, SerialNumber, and AssetAssignee. Each is configured as an EF owned type in AssetDbContext and stored inline on the same row as the aggregate — there are no separate value-object tables. Value objects use structural equality, so two instances are equal when their components match.
Confirmed persistence behavior
| Value object | Domain purpose | Stored column(s) | Conversion | Nullability | Validation | Equality | Index implication |
|---|---|---|---|---|---|---|---|
AssetCode | Business asset code / tag | AssetCode varchar(80) | Owned type in AssetDbContext | Required (navigation required) | Upper-cased, trimmed, ≤80, required | Structural, by Value | Non-unique IX_Assets_AssetCode; uniqueness is application-layer only |
AssetName | Display name | AssetName varchar(200) | Owned type | Required | Trimmed, ≤200, required | Structural, by Value | Not separately indexed |
SerialNumber | Manufacturer serial | SerialNumber varchar(160) | Owned type | Required at DB (empty string allowed) | ≤160; empty allowed for requests/consumables; IsEmpty helper | Structural, by Value | Not indexed; no uniqueness |
AssetAssignee | Current assignee reference | AssignedToUserId int?, LaborId int? | Owned type | Both nullable | None when unassigned; IsAssigned when set | Structural, by both components | Not separately indexed; owned-property filters use no dedicated index |
- Storage model: all four value objects persist inline on the
Assetsrow via EF owned-type configuration; there are no side tables. - Query implications: filtering by an owned property (for example the assignee's
UserId) is possible but is not backed by a dedicated index — the indexed access paths are the tenant-status, tenant-type, workflow-instance, compatibility-id, and non-unique asset-code indexes. See Indexes and Constraints. - Equality: value objects derive equality from their components (
GetEqualityComponents), so comparisons and change detection are value-based, not reference-based.
Non-persisted computed / ignored members
These members exist in the domain but are not stored:
| Member | Kind | Note |
|---|---|---|
Asset.DomainEvents | Ignored (Ignore) | Not mapped |
Asset.IsWorkflowManaged | Computed | Derived from workflow linkage |
Asset.IsDeletable | Computed | Derived from status (Available, Requested, Rejected) |
AssetAssignee.None | Computed | Unassigned sentinel |
AssetAssignee.IsAssigned | Computed | True when an id is present |
AssetDocumentReference.HasStoredContent | Computed | Derived from DocumentServiceId presence |
SerialNumber.IsEmpty | Computed | True when serial is empty |
Classification
Implemented owned value-object persistence with a Transitional (non-hardened) uniqueness posture.
Requires confirmation
Whether AssetCode should gain a per-tenant database unique constraint, and whether SerialNumber should carry any uniqueness, are not decided in source and require confirmation.
Diagram
Related Articles
See Also
Keywords
- Asset value objects
- Value-Object Conversions
- Value-object conversions
Source References
microservices/src/asset-service/Domain/Common/ValueObjects.csmicroservices/src/asset-service/Infrastructure/AssetDbContext.csmicroservices/src/asset-service/Domain/Asset/Asset.csmicroservices/src/asset-service/Domain/Common/DomainPrimitives.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-17
- Review cycle: Quarterly