FractalDataWorks.Commands.Data 0.6.0-rc.1

This is a prerelease version of FractalDataWorks.Commands.Data.
dotnet add package FractalDataWorks.Commands.Data --version 0.6.0-rc.1
                    
NuGet\Install-Package FractalDataWorks.Commands.Data -Version 0.6.0-rc.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FractalDataWorks.Commands.Data" Version="0.6.0-rc.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FractalDataWorks.Commands.Data" Version="0.6.0-rc.1" />
                    
Directory.Packages.props
<PackageReference Include="FractalDataWorks.Commands.Data" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FractalDataWorks.Commands.Data --version 0.6.0-rc.1
                    
#r "nuget: FractalDataWorks.Commands.Data, 0.6.0-rc.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FractalDataWorks.Commands.Data@0.6.0-rc.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FractalDataWorks.Commands.Data&version=0.6.0-rc.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=FractalDataWorks.Commands.Data&version=0.6.0-rc.1&prerelease
                    
Install as a Cake Tool

FractalDataWorks.Commands.Data

Data command implementations for the FractalDataWorks framework, providing a type-safe API for data operations across different backends.

Overview

This package provides concrete implementations of data commands that work with SQL databases, REST APIs, file systems, and other data sources. Commands are translated by backend-specific translators to native operations.

Installation

<PackageReference Include="FractalDataWorks.Commands.Data" Version="1.0.0" />

Architecture

Application Code
    |
DataCommands (Universal)
    |
Translators (Backend-Specific)
    |
DataGateway
    |
Connections (Protocol)
    |
Data Sources

Projects

Project Purpose
FractalDataWorks.Commands.Data.Abstractions Interfaces and base classes
FractalDataWorks.Commands.Data Concrete command implementations
FractalDataWorks.Commands.Data.Extensions Builder methods for commands

Command Types

From QueryCommand.cs:59-106:

[TypeOption(typeof(DataCommands), "Query")]
public sealed class QueryCommand<T> : DataCommandBase<IEnumerable<T>>, IQueryCommand
{
    public QueryCommand(string containerName)
        : base("Query", containerName)
    {
    }

    public IFilterExpression? Filter { get; init; }
    public IProjectionExpression? Projection { get; init; }
    public IOrderingExpression? Ordering { get; init; }
    public IPagingExpression? Paging { get; init; }
    public IAggregationExpression? Aggregation { get; init; }
    public IReadOnlyList<IJoinExpression> Joins { get; init; } = [];
}

Available commands:

  • QueryCommand<T> - Retrieve data (SELECT)
  • InsertCommand<T> - Add new data (INSERT)
  • UpdateCommand<T> - Modify existing data (UPDATE)
  • DeleteCommand - Remove data (DELETE)
  • BulkInsertCommand<T> - Bulk insert operations

Usage

Query with Filter

Filters use a composite pattern with FilterCondition (leaf) and FilterGroup (composite).

From FilterCondition.cs:26-43:

public sealed record FilterCondition : IFilterCondition, IFilterNode
{
    public required string PropertyName { get; init; }
    public required IFilterOperator Operator { get; init; }
    public object? Value { get; init; }
}

From FilterExpression.cs:51-57:

public sealed class FilterExpression : IFilterExpression
{
    public IFilterNode? Root { get; init; }
}

Example - simple filter:

var command = new QueryCommand<Customer>("Customers")
{
    Filter = new FilterExpression
    {
        Root = new FilterCondition
        {
            PropertyName = nameof(Customer.IsActive),
            Operator = FilterOperators.Equal,
            Value = true
        }
    }
};

Example - complex filter with grouping (from FilterGroup.cs:23-34):

// (Name LIKE '%Acme%' OR Name LIKE '%Corp%') AND IsActive = true
var command = new QueryCommand<Customer>("Customers")
{
    Filter = new FilterExpression
    {
        Root = new FilterGroup
        {
            Operator = LogicalOperator.And,
            Nodes =
            [
                new FilterGroup
                {
                    Operator = LogicalOperator.Or,
                    Nodes =
                    [
                        new FilterCondition
                        {
                            PropertyName = "Name",
                            Operator = FilterOperators.Contains,
                            Value = "Acme"
                        },
                        new FilterCondition
                        {
                            PropertyName = "Name",
                            Operator = FilterOperators.Contains,
                            Value = "Corp"
                        }
                    ]
                },
                new FilterCondition
                {
                    PropertyName = "IsActive",
                    Operator = FilterOperators.Equal,
                    Value = true
                }
            ]
        }
    }
};

Query with Ordering and Paging

From OrderingExpression.cs:9-16 and PagingExpression.cs:8-20:

var command = new QueryCommand<Customer>("Customers")
{
    Ordering = new OrderingExpression
    {
        OrderedFields =
        [
            new OrderedField
            {
                PropertyName = "Name",
                Direction = SortDirections.Ascending
            }
        ]
    },
    Paging = new PagingExpression
    {
        Skip = 0,
        Take = 50
    }
};

Insert Command

From InsertCommand.cs:35-47:

[TypeOption(typeof(DataCommands), "Insert")]
public sealed class InsertCommand<T> : DataCommandBase<int, T>
{
    public InsertCommand(string containerName, T data)
        : base("Insert", containerName, data)
    {
    }
}

Usage:

var customer = new Customer
{
    Name = "Acme Corp",
    Email = "contact@acme.com",
    IsActive = true
};

var command = new InsertCommand<Customer>("Customers", customer);

Update Command

From UpdateCommand.cs:47-65:

[TypeOption(typeof(DataCommands), "Update")]
public sealed class UpdateCommand<T> : DataCommandBase<int, T>, IFilterableCommand
{
    public UpdateCommand(string containerName, T data)
        : base("Update", containerName, data)
    {
    }

    public IFilterExpression? Filter { get; init; }
}

Usage:

var customer = new Customer { Id = 123, Name = "Acme Corp Updated", IsActive = false };
var command = new UpdateCommand<Customer>("Customers", customer)
{
    Filter = new FilterExpression
    {
        Root = new FilterCondition
        {
            PropertyName = "Id",
            Operator = FilterOperators.Equal,
            Value = 123
        }
    }
};

Delete Command

From DeleteCommand.cs:45-62:

[TypeOption(typeof(DataCommands), "Delete")]
public sealed class DeleteCommand : DataCommandBase<int>, IFilterableCommand
{
    public DeleteCommand(string containerName)
        : base("Delete", containerName)
    {
    }

    public IFilterExpression? Filter { get; init; }
}

Usage:

var command = new DeleteCommand("Customers")
{
    Filter = new FilterExpression
    {
        Root = new FilterCondition
        {
            PropertyName = "IsActive",
            Operator = FilterOperators.Equal,
            Value = false
        }
    }
};

Filter Operators

From FilterOperators.cs:40-50, the TypeCollection provides static properties for each operator:

Operator SQL OData
FilterOperators.Equal = eq
FilterOperators.NotEqual <> ne
FilterOperators.GreaterThan > gt
FilterOperators.GreaterThanOrEqual >= ge
FilterOperators.LessThan < lt
FilterOperators.LessThanOrEqual <= le
FilterOperators.Contains LIKE contains
FilterOperators.StartsWith LIKE startswith
FilterOperators.EndsWith LIKE endswith
FilterOperators.In IN in
FilterOperators.IsNull IS NULL eq null
FilterOperators.IsNotNull IS NOT NULL ne null

Execution via DataGateway

Commands are executed through the IDataGateway interface, which routes commands to the appropriate connection based on ConnectionName.

From IDataGateway.cs:14-24:

public interface IDataGateway
{
    Task<IGenericResult<T>> Execute<T>(IDataCommand command, CancellationToken cancellationToken = default);
}

Usage:

var command = new QueryCommand<Customer>("Customers")
{
    Filter = new FilterExpression
    {
        Root = new FilterCondition
        {
            PropertyName = nameof(Customer.IsActive),
            Operator = FilterOperators.Equal,
            Value = true
        }
    }
};

var result = await gateway.Execute<IEnumerable<Customer>>(command, cancellationToken);

if (result.IsSuccess)
{
    foreach (var customer in result.Value)
    {
        Console.WriteLine(customer.Name);
    }
}
else
{
    Console.WriteLine($"Error: {result.Error}");
}

Framework Patterns

Railway-Oriented Programming

All command execution returns IGenericResult<T>, enabling explicit error handling without exceptions.

TypeCollections

Commands and operators use TypeCollections instead of enums, providing:

  • Compile-time type safety
  • Cross-assembly extensibility
  • No switch statements needed
  • Each operator knows its SQL/OData representations

From EqualOperator.cs:10-48:

[TypeOption(typeof(FilterOperators), "Equal")]
public sealed class EqualOperator : FilterOperatorBase
{
    public EqualOperator()
        : base(
            id: 1,
            name: "Equal",
            sqlOperator: "=",
            odataOperator: "eq",
            requiresValue: true)
    {
    }

    public override string FormatODataValue(object? value)
    {
        // Operator knows its own formatting
    }
}

Next Steps

  1. See FractalDataWorks.Data.MsSql for SQL Server translator implementation
  2. See FractalDataWorks.Data.Rest for REST API translator implementation
  3. See the wiki for architecture details and patterns
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on FractalDataWorks.Commands.Data:

Package Downloads
FractalDataWorks.Commands.Data.Extensions

Development tools and utilities for the FractalDataWorks ecosystem. Build:

FractalDataWorks.Calculations.Aggregations

Development tools and utilities for the FractalDataWorks ecosystem. Build:

FractalDataWorks.Configuration.MsSql

Development tools and utilities for the FractalDataWorks ecosystem. Build:

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.0-rc.1 65 2/9/2026
Loading failed