Skip to main content

Overview

EasyAF enforces an opinionated database design structure that promotes consistency, maintainability, and reduces boilerplate code. By implementing a set of composable interfaces, your entities automatically gain common functionality that works seamlessly with Entity Framework Core and OData Restier.

Core Concepts

The EasyAF framework uses interface composition to build database entities with common patterns. Rather than inheriting from a base class, you implement specific interfaces that add the functionality you need. This approach provides flexibility while maintaining consistency across your data model.

Benefits of the Interface-Based Approach

  • Composability: Mix and match interfaces to get exactly the functionality you need
  • Consistency: Common patterns across all tables
  • Code Generation: Automatic handling of audit fields, state management, and more
  • Type Safety: Generic interfaces ensure compile-time type checking
  • OData Integration: Seamless integration with OData queries and filters

Naming Conventions and Design Principles

EasyAF enforces specific naming conventions that enhance code generation, improve IntelliSense experiences, and create predictable patterns across your codebase.

Primary Keys: Always “Id”

Primary key properties are always named Id, never prefixed with the table name.
Why?
  • Serialization efficiency: Shorter property names reduce payload size
  • Predictability: Id is always the primary key, {TableName}Id is always a foreign key
  • Consistency: Universal pattern across all entities

Foreign Keys: Id

Foreign key properties follow the pattern {TableName}Id to clearly indicate relationships.

Exception: Semantic Naming for Clarity

Use more descriptive names when the relationship role needs clarification:
Never create direct foreign keys to User tables in business entities. This pollutes object models and creates unnecessary coupling. Use filtering in queries instead:

Date Properties: Prefix with “Date”

All date/time properties should be prefixed with Date followed by the semantic meaning.
Benefits:
  • Code generation: Tools can easily identify and process date fields
  • IntelliSense grouping: All date properties appear together in autocomplete lists
  • Consistency: Predictable naming across the entire codebase
  • Clarity: Immediately clear what the property represents

Boolean Properties: “Is” or “Has” Prefix

Boolean properties must be prefixed with Is or Has to indicate state or possession, typically in present tense.
Guidelines:
  • Use Is for state: IsActive, IsVisible, IsEnabled, IsPublished
  • Use Has for possession or capability: HasOptions, HasChildren, HasAccess
  • Present tense preferred: IsActive over WasActive
  • Positive phrasing preferred: IsVisible over IsHidden (when practical)

DisplayName: UI-Focused Property

The DisplayName property (from IHumanReadable) is always the primary user-facing text representation of an entity.
Rules:
  • DisplayName is what appears in dropdowns, lists, and labels
  • Other “name” properties can exist for specific purposes (LegalName, CompanyName, etc.)
  • If showing users a single text value, use DisplayName

Database Enums and SortOrder

The SortOrder property in IDbEnum serves a dual purpose: UI ordering and C# enum mapping.
Benefits:
  • Avoids complex EF Core enum mapping configuration
  • Maintains type safety in business logic via C# enums
  • Provides flexibility to change display text without code changes
  • Works reliably with OData (which has inconsistent enum support)
Use SortOrder as the bridge between compile-time C# enums and runtime database enums. This gives you the best of both worlds: type safety in code and flexibility in data.

Entity Identification

IIdentifiable<T>

The foundation of every entity in EasyAF. This interface ensures your entity has a unique identifier.
Common Usage:
EasyAF recommends using Guid as the identifier type for most entities to avoid identity conflicts in distributed systems and simplify data synchronization.

Audit Tracking

Track when entities are created and updated, and by whom.

ICreatedAuditable

Tracks when an entity was created.

IUpdatedAuditable

Tracks when an entity was last updated.
DateUpdated is nullable because it’s only set after the first update, not on creation.

ICreatorTrackable<T>

Tracks which user created the entity.

IUpdaterTrackable<T>

Tracks which user last updated the entity.
Complete Audit Example:

Active/Inactive Tracking

IActiveTrackable

Implements soft delete functionality by tracking whether an entity is active or inactive.
Usage:
Use IActiveTrackable instead of hard deletes to maintain data integrity and enable historical reporting.

User-Friendly Display

IHumanReadable

Provides a consistent property for displaying entity names to users.
Usage:

Ordering and Sorting

ISortable

Enables manual ordering of entities in lists and dropdowns.
Usage:

Database-Driven Enumerations

Traditional enums in code can cause problems when business logic changes. EasyAF provides a pattern for database-driven enumerations that can be updated without code changes.

IDbEnum

The base interface for all database enumerations.
IDbEnum combines multiple interfaces, giving you identity, active tracking, human-readable display, and sorting in one declaration.
Usage:

IDbStatusEnum

Specialized enumeration for tracking entity status.
Usage:

IDbStateEnum

Advanced enumeration for state machine workflows, providing navigation between states.
Usage:

Linking Entities to Enumerations

IHasStatus<T>

Links an entity to a status enumeration.
Usage:

IHasState<T>

Links an entity to a state enumeration for workflow management.
Usage:

Complete Entity Example

Here’s a comprehensive example combining multiple interfaces:

Best Practices

1. Start with the Basics

Always implement IIdentifiable<Guid> as your foundation:

2. Add Audit Tracking for Business Entities

For entities that track business operations, implement full audit tracking:

3. Use Soft Deletes

Prefer IActiveTrackable over hard deletes:

4. Leverage Database Enumerations

Replace code enums with database enumerations for flexibility:

5. Consistent Interface Ordering

Use a consistent order when implementing multiple interfaces for better readability:
  1. IIdentifiable<T>
  2. Audit interfaces (ICreatedAuditable, etc.)
  3. IActiveTrackable
  4. IHumanReadable
  5. ISortable
  6. Status/State interfaces
  7. Custom interfaces

Integration with Entity Framework Core

Configure your DbContext to respect these interfaces:

Summary

EasyAF’s interface-based table design provides:
  • Consistency: Common patterns across all entities
  • Flexibility: Compose interfaces to match your needs
  • Maintainability: Centralized definitions reduce duplication
  • Integration: Seamless OData and EF Core support
  • Scalability: Database-driven enumerations adapt to changing business requirements
By following these patterns, you’ll create a robust, maintainable data model that works seamlessly with the EasyAF framework and reduces boilerplate throughout your application.