Skip to content

Add SQL Server 2025 JSON data type support#1

Draft
bold-hen wants to merge 5 commits into
letarak:masterfrom
bold-hen:feature/json-type-support
Draft

Add SQL Server 2025 JSON data type support#1
bold-hen wants to merge 5 commits into
letarak:masterfrom
bold-hen:feature/json-type-support

Conversation

@bold-hen

@bold-hen bold-hen commented Mar 16, 2026

Copy link
Copy Markdown

Summary

  • Add native json data type support for SQL Server 2025 (v17+), with nvarchar(max) fallback on older versions
  • Introduce JsonType base class for POCO types stored as single JSON columns, and JsonTypeArray<T> for JSON array collections with generic type validation
  • Full LINQ translation: property access via JSON_VALUE, array expansion via CROSS APPLY OPENJSON, joins and aggregation on JSON fields
  • Automatic inner property mutation tracking via Weaver-injected INotifyPropertyChanged — the ORM Weaver detects JsonType subclasses and injects OnPropertyChanged calls into property setters, so changes like owner.JsonField.Name = "x" are tracked without whole-object reassignment
  • Add numeric Parse method compilers (int.Parse, decimal.Parse, etc.) so JSON property access works in join keys and server-side expressions
  • SQL Server v17 driver with Compiler, Translator, TypeMapper, ServerInfoProvider, and Extractor

Key design decisions

  • JsonType is a lightweight base class implementing INotifyPropertyChanged — properties are plain C# auto-properties serialized via System.Text.Json
  • Change tracking uses Weaver-injected INPC: ImplementJsonPropertyNotificationTask appends OnPropertyChanged("PropName") IL to each auto-property setter; JsonFieldAccessor subscribes to PropertyChanged and immediately writes changes to the entity tuple
  • JsonTypeArray<T> subscribes to each item's PropertyChanged for inner mutations, and persists eagerly on collection mutations (Add/Remove/Clear)
  • JsonTypeArray<T> element type validated at domain build time (must inherit from JsonType)

Test plan

  • Verify json column type on SQL Server 2025, nvarchar(max) on older versions
  • Verify change tracking: whole-object replacement, inner property mutation, null assignment
  • Verify JsonTypeArray tracking: Add, Remove, Clear, indexer set, inner item mutation
  • Verify server-side LINQ: Select with JSON properties (string, int, decimal, bool, DateTime), mixed entity+JSON fields, aggregation (Sum/Count)
  • Verify Join operations: JSON int/string keys, entity vs JSON keys, join with SelectMany
  • Verify SelectMany projections: basic, filtered, with anonymous types, mixed entity+array fields

bold-hen and others added 5 commits March 13, 2026 23:41
Introduce comprehensive JSON type support for the ORM, enabling fields
derived from the new JsonType base class to be stored as JSON columns
with LINQ translation for property access via JSON_VALUE/JSON_QUERY.

Core type system:
- JsonType abstract base class as marker for JSON-storable types
- SqlType.Json for the native SQL Server 2025 json data type
- FieldAttributes.Json flag and FieldInfo.IsJson property
- JsonFieldAccessor for System.Text.Json serialization/deserialization
- FieldDef/TypeBuilder support for single-column JSON field mapping

SQL DOM layer:
- SqlFunctionType entries for JSON_VALUE, JSON_QUERY, JSON_MODIFY,
  ISJSON, and JSON_PATH_EXISTS
- SqlDml factory methods for all JSON functions
- SqlTranslator mappings to SQL function names
- DataTypeCollection.Json property for type registration

SQL Server v17 driver:
- New v17 driver inheriting from v13 for SQL Server 2025+
- ServerInfoProvider registers native json data type
- Compiler, Translator, Extractor, TypeMapper implementations
- DriverFactory routes version >= 17 to v17 driver
- Fallback to nvarchar(max) on older SQL Server versions

LINQ translation:
- JsonFieldExpression with JSON path tracking for property access
- ExtendedExpressionType.JsonField and visitor infrastructure
- Translator.GetMember handles JSON member access via CreatePropertyAccess
- ExpressionMaterializer generates JsonExpressionHelper.JsonValue calls
- JsonCompilers translate to SqlDml.JsonValue/JsonQuery for SQL generation
- ColumnGatherer support for JSON field column tracking
- Type conversion via Expression.Convert with Parse methods for non-string
  properties (generates CAST in SQL)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix JsonCompilers: add TargetKind.Static flag for static method compilers
- Fix Validator: recognize JsonType subclasses as valid field types
- Fix ModelInspector: add early return for JSON fields to prevent
  erroneous model type lookup
- Add TestJsonInOrm integration test project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ve tests

- Add JsonTypeArray<T> generic collection type for JSON arrays with change tracking
- Add JsonArrayFieldAccessor and JsonTrackedCollection for proper persistence
- Add OpenJsonProvider (OPENJSON) support for SelectMany over JSON arrays
- Add numeric Parse method compilers so JSON property access works in joins/expressions
- Add JsonTypeArray<T> element type validation (must inherit from JsonType)
- Add comprehensive NUnit tests covering SQL column types, change tracking,
  server-side Select, Join operations, and SelectMany projections
- Update SQL Server v17 driver to handle native JSON type compilation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add snapshot-based dirty checking for scalar JsonType fields via
  JsonFieldValueAdapter<T> — inner property mutations (e.g.,
  owner.JsonField.StringField = "x") are now automatically detected
  and persisted without requiring whole-object reassignment
- Convert JsonFieldAccessor to CachingFieldAccessor pattern so repeated
  access returns the same cached instance
- Add IJsonFieldValueAdapter interface with FlushIfDirty() for pre-persist
  snapshot comparison
- Extend JsonTypeArray with snapshot comparison to detect inner item
  property mutations (e.g., array[0].Name = "x")
- Add session-level JsonFieldAdapters registry and FlushDirtyJsonFields()
  hook in Session.Persist before EntityChangeRegistry check
- Restructure tests: move LINQ tests to Linq/JsonLinqTest.cs, keep
  storage/change-tracking tests in Storage/JsonTypeTest.cs
- Remove TestJsonInOrm scratch project from solution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pertyChanged

Replace snapshot-based dirty checking with proper INPC pattern:

- JsonType now implements INotifyPropertyChanged with OnPropertyChanged()
- ORM Weaver detects JsonType subclasses (new PersistentTypeKind.JsonType)
  and injects OnPropertyChanged("PropName") calls into property setters
  via ImplementJsonPropertyNotificationTask
- JsonFieldAccessor subscribes to PropertyChanged on cached instances and
  immediately writes changes to the entity tuple (no flush-time re-serialization)
- JsonTypeArray subscribes to each item's PropertyChanged for inner mutations
- Remove snapshot infrastructure: delete JsonFieldValueAdapter, remove
  IJsonFieldValueAdapter, FlushDirtyJsonFields, and Session-level registry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bold-hen bold-hen changed the title Feature/json type support Add SQL Server 2025 JSON data type support Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant