Table of Contents

Alternate keys

Alternate keys allow you to define unique identifiers alternative to the primary key of an entity. They are particularly useful in data import scenarios and communication with external partners.

Definition

An alternate key is a set of properties that, when combined, uniquely identify a record in a database table. It can be composed of one or more entity properties.

Main characteristics

  • Guaranteed uniqueness: An alternate key automatically generates a unique index on the associated database table
  • Search methods: Search methods are generated in repositories to facilitate data access
  • Usage in entity views: An alternate key can serve as the key for an entity view
  • Import scenarios: They are designed to simplify import processes and exchanges with external systems

Declaring an alternate key

Alternate keys are defined in the module's metadata/EntityAlternateKeys folder. Each alternate key has a name and specifies which properties compose it.

An alternate key can be:

  • Simple: Composed of a single property (e.g., ExternalID, Code)
  • Composite: Composed of multiple properties (e.g., CategoryID + Code)

Composite alternate keys can combine both scalar properties and foreign keys.

Database impact

Each alternate key generates a unique index on the associated table when you trigger metadata generation from the entity. This ensures data integrity and improves search performance.

To create the unique index, click the "Generate metadata" button from the entity in Neos Studio.

Generated methods in repositories

For each defined alternate key, the Neos generator automatically creates search methods in the entity's repository.

Example with IAKProductRepository

Generated file: TechnicalDemos.Domain/Persistence/IAKProductRepository.cs

public interface IAKProductRepository : IRepository<AKProduct>
{
    // Methods for primary key
    AKProduct Get(int id);
    AKProduct? Find(int id);
    Task<AKProduct> GetAsync(int id);
    Task<AKProduct?> FindAsync(int id);
    
    // Methods for alternate key "ExternalKey"
    AKProduct GetByExternalKey(string? externalID);
    AKProduct? FindByExternalKey(string? externalID);
    Task<AKProduct> GetByExternalKeyAsync(string? externalID, CancellationToken cancellationToken);
    Task<AKProduct?> FindByExternalKeyAsync(string? externalID, CancellationToken cancellationToken);
    
    // Methods for alternate key "NaturalKey" (composite)
    AKProduct GetByNaturalKey(int categoryID, string code);
    AKProduct? FindByNaturalKey(int categoryID, string code);
    Task<AKProduct> GetByNaturalKeyAsync(int categoryID, string code, CancellationToken cancellationToken);
    Task<AKProduct?> FindByNaturalKeyAsync(int categoryID, string code, CancellationToken cancellationToken);
}

Method behavior

Alternate key search methods follow the standard pattern:

  • Get*: Throws an exception if the entity is not found
  • Find*: Returns null if the entity is not found

Important: These methods search first in the cache of the Unit of Work, then query the database only if the element is not present. This optimizes performance and avoids unnecessary queries.

Complete example: TechnicalDemos Module

The AlternateKeys module in the TechnicalDemos cluster provides complete examples of alternate key usage.

Module structure

The module contains:

  • Entities: AKCustomer, AKProduct, AKProductCategory, AKOrder, AKOrderDetail
  • Alternate keys:
    • ExternalKey: Simple key based on ExternalID
    • NaturalKey: Business key (simple or composite depending on the entity)
  • Entity views: Examples with alternate key as primary key
  • UI views: Demonstration of interface usage

Accessing the examples

To explore the module and its examples:

  1. See the TechnicalDemos cluster for installation instructions
  2. Navigate to the "Alternate Keys" menu in the application

See also