Skip to content

[Decision Needed] Path B: Downgrade DataProvider to use only .NET Standard 2.0 APIs #23

@MelbourneDeveloper

Description

@MelbourneDeveloper

Problem Statement

H5 only supports .NET Standard 2.0 APIs for transpilation to JavaScript. To share DataProvider code with Dashboard.Web, we must downgrade DataProvider to use ONLY netstandard2.0 APIs when targeting that framework.

Current State

  • DataProvider targets net9.0 with .NET 9.0 dependencies
  • System.Text.Json 9.0, Npgsql 9.0, etc. require .NET 6.0+ APIs
  • Generated code uses modern C# features and .NET APIs

Implementation Strategy: Partial Class File Separation

DO NOT litter code with `#if` conditionals! Instead, use partial classes with separate implementation files.

CORRECT Pattern:

Main code (common logic only, or minimal):

// DatabaseHelper.cs
public static partial class DatabaseHelper
{
    // Common methods that work on all platforms
    public static string ValidateConnection(string connStr) => !string.IsNullOrEmpty(connStr);
}

NetStandard 2.0 implementation:

// DatabaseHelper.NetStandard2_0.cs
#if NETSTANDARD2_0
public static partial class DatabaseHelper
{
    public static string SerializeData(object obj) 
        => Newtonsoft.Json.JsonConvert.SerializeObject(obj);
    
    public static T DeserializeData<T>(string json) 
        => Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
}
#endif

Modern .NET implementation:

// DatabaseHelper.Modern.cs
#if !NETSTANDARD2_0
public static partial class DatabaseHelper
{
    public static string SerializeData(object obj) 
        => System.Text.Json.JsonSerializer.Serialize(obj);
    
    public static T DeserializeData<T>(string json) 
        => System.Text.Json.JsonSerializer.Deserialize<T>(json);
}
#endif

Key Principle:

  • Main code contains common logic that works on ALL platforms
  • Platform-specific methods are implemented DIRECTLY in their respective partial files
  • The #if ensures only ONE implementation compiles per target framework
  • NO abstract/interface-style declarations - each partial file has COMPLETE method implementations

Required Changes

  1. Multi-target Configuration

    <TargetFrameworks>netstandard2.0;net8.0;net9.0</TargetFrameworks>
  2. Conditional Dependencies

    <PackageReference Include="System.Text.Json" Version="9.0.0" 
                      Condition="'$(TargetFramework)' != 'netstandard2.0'" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" 
                      Condition="'$(TargetFramework)' == 'netstandard2.0'" />
  3. Partial Class File Organization

    • Main file: Common logic that works everywhere
    • Platform files: Complete method implementations (NOT declarations)
    • ClassName.NetStandard2_0.cs - wrapped in #if NETSTANDARD2_0
    • ClassName.Modern.cs - wrapped in #if !NETSTANDARD2_0
  4. Generated Code Constraints

    • Generated .g.cs files must ONLY use netstandard2.0 APIs
    • No conditional compilation in generated code
    • Use lowest common denominator APIs in templates
  5. File Naming Convention

    • SomeClass.cs - Common logic (platform-agnostic)
    • SomeClass.NetStandard2_0.cs - NetStandard 2.0 implementation
    • SomeClass.Modern.cs - .NET 8/9 implementation

Files to Modify

  • Directory.Build.props - Multi-targeting config
  • DataProvider/DataProvider/DataProvider.csproj
  • Lql/Lql/Lql.csproj
  • Sync/Sync/Sync.csproj
  • Split any files using .NET 6+ APIs into partial classes
  • Update code generation templates

Success Criteria

  • DataProvider builds for netstandard2.0, net8.0, net9.0
  • Main code files contain ZERO #if conditionals
  • Platform-specific implementations in separate partial files
  • Generated .g.cs code compiles in Dashboard.Web (H5/netstandard2.0)
  • H5 can transpile generated records to JavaScript
  • All tests pass on net8.0 and net9.0

Example File Structure

DataProvider/
├─ DatabaseEffects.cs                  # Common logic
├─ DatabaseEffects.NetStandard2_0.cs  # NS2.0 methods (#if NETSTANDARD2_0)
└─ DatabaseEffects.Modern.cs          # Modern methods (#if !NETSTANDARD2_0)

Mutually Exclusive With

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions