EntityHelper - pengdows/pengdows.crud GitHub Wiki

Table of Contents

EntityHelper

EntityHelper<TEntity, TRowID> is the heart of pengdows.crud’s dynamic SQL mapping. It provides reflection-backed mapping between POCOs and SQL, enabling parameterized CRUD operations across supported databases.

EntityHelper<TEntity, TRowID> is the primary utility in pengdows.crud for mapping entities to SQL. It uses reflection, precompiled accessors, and context-aware parameter and naming strategies to generate safe, efficient, portable SQL for CRUD operations.

Purpose

  • Generate parameterized SQL for INSERT, SELECT, UPDATE, and DELETE
  • Map database results to POCOs using tracked readers
  • Enforce database-specific rules and auditing
  • Handle version fields and optimistic concurrency

Instantiation

var helper = new EntityHelper<User, Guid>(context, serviceProvider);
  • TEntity your entity class
  • TRowID — the pseudokey type (typically int or Guid)
  • context — is the DatabaseContext that will be used to create sqlcontainers, sql wrapping characters, and parameters.
  • serviceProvider — is your dependency injection to grab additional items.

Key Features

  • Requires exactly one [Id] property
  • Supports multi-column [PrimaryKey] fields
  • Supports [Version] field for optimistic concurrency
  • Handles [CreatedBy], [CreatedOn], [LastUpdatedBy], [LastUpdatedOn] automatically via DI using the Audit Handling

CRUD Methods

  • BuildCreate(entity) — generates INSERT
  • BuildRetrieve(ids) — generates SELECT WHERE ID IN (...)
  • BuildRetrieve(entities) — generates SELECT with composite PK filters
  • BuildUpdateAsync(entity) — generates UPDATE (optionally checks version)
  • BuildDelete(id) — generates DELETE

Row Mapping

  • Uses ITrackedReader (extends IDataReader) for safe disposal
  • Uses cached compiled setters for high-performance hydration
  • Applies TypeCoercionHelper for cross-database coercion (e.g., string→enum)

Audit Handling

  • Fields marked with [CreatedBy], [CreatedOn], etc. are auto-filled
  • Uses registered IAuditContextProvider<T> from DI
  • Populated on insert or update
  • All timestamps assumed to be UTC

Version Handling

  • BuildUpdateAsync(entity, loadOriginal: true) compares current values to a reloaded original row
  • Columns that haven't changed will not be included in the UPDATE
  • This improves performance and avoids race conditions on unnecessary writes
  • Columns marked as [CreatedBy] or [CreatedOn] are always excluded from updates to preserve audit traceability
  • Version fields are incremented automatically during updates
  • If present, update WHERE clauses include Version = ? checks to enforce optimistic concurrency

Parameter Safety

  • Automatically generates parameter names using MakeParameterName
  • Follows provider’s requirements for @name, :name, or ?
  • Checks against MaxParameterLimit before issuing bulk WHEREs

Best Practices

  • Use BuildRetrieve with object lists for composite key filters
  • Use BuildUpdateAsync(..., loadOriginal: true) to skip unchanged fields
  • Catch TooManyParametersException for wide filters on constrained databases
  • Subclass for custom query helpers (e.g., FindByEmail)

Constraints

  • Only one [Id] property is allowed
  • [PrimaryKey] fields must not overlap with [Id], audit fields, or [Version]
  • Requires a unique pseudokey per table to use EntityHelper auto-SQL

Related Pages

⚠️ **GitHub.com Fallback** ⚠️