FractalDataWorks.Services.Data.Abstractions 0.4.0-preview.6

This is a prerelease version of FractalDataWorks.Services.Data.Abstractions.
The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package FractalDataWorks.Services.Data.Abstractions --version 0.4.0-preview.6
                    
NuGet\Install-Package FractalDataWorks.Services.Data.Abstractions -Version 0.4.0-preview.6
                    
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.Services.Data.Abstractions" Version="0.4.0-preview.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FractalDataWorks.Services.Data.Abstractions" Version="0.4.0-preview.6" />
                    
Directory.Packages.props
<PackageReference Include="FractalDataWorks.Services.Data.Abstractions" />
                    
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.Services.Data.Abstractions --version 0.4.0-preview.6
                    
#r "nuget: FractalDataWorks.Services.Data.Abstractions, 0.4.0-preview.6"
                    
#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.Services.Data.Abstractions@0.4.0-preview.6
                    
#: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.Services.Data.Abstractions&version=0.4.0-preview.6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=FractalDataWorks.Services.Data.Abstractions&version=0.4.0-preview.6&prerelease
                    
Install as a Cake Tool

FractalDataWorks.Services.Data.Abstractions

Data gateway abstractions for universal data command execution.

Overview

This package provides the core abstraction for the DataGateway - a routing service that directs universal data commands to the appropriate connection. With the Built-In Translator Pattern, the DataGateway is minimal, as connections own their translators and handle all translation logic internally.

Key Principle

The DataGateway is a connection router. It does NOT manage translators or translation logic.

Architecture (Built-In Translator Pattern)

Application Code
    |
IDataGateway.Execute(IDataCommand)
    |
DataGateway (simple routing)
    +-- Look up connection by name
    +-- Route command to connection
    |
IDataConnection (owns translator)
    +-- Translate IDataCommand -> IConnectionCommand
    +-- Execute IConnectionCommand
    +-- Return IGenericResult<T>

Core Interface

IDataGateway

From IDataGateway.cs:1-24:

using System.Threading;
using System.Threading.Tasks;
using FractalDataWorks.Commands.Data.Abstractions;
using FractalDataWorks.Data.Abstractions;
using FractalDataWorks.Results;

namespace FractalDataWorks.Services.Data.Abstractions;

/// <summary>
/// Service that routes data commands to the appropriate connection.
/// The DataGateway selects the correct connection based on the command's ConnectionName
/// and delegates execution to that connection.
/// </summary>
public interface IDataGateway
{
    /// <summary>
    /// Executes a data command by routing it to the appropriate connection.
    /// </summary>
    /// <typeparam name="T">The result type.</typeparam>
    /// <param name="command">The data command containing ConnectionName.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The execution result.</returns>
    Task<IGenericResult<T>> Execute<T>(IDataCommand command, CancellationToken cancellationToken = default);
}

Usage

For usage examples with QueryCommand<T> and FilterExpression, see the FractalDataWorks.Commands.Data package.

Basic Gateway Usage

The IDataGateway accepts any IDataCommand and routes it to the appropriate connection based on ConnectionName. See the unit tests for actual invocation patterns.

For command creation examples using QueryCommand<T>, see the actual source code in MsSqlConfigurationSource.cs.

From MsSqlConfigurationSource.cs:170-178:

var queryCommand = new QueryCommand<ConfigurationHeaderEntity>("Configuration")
{
    Filter = filter
};

var result = await _source.Connection!.Execute<IEnumerable<ConfigurationHeaderEntity>>(
    queryCommand,
    ConfigurationContainers.Configuration,
    cancellationToken).ConfigureAwait(false);

Error Handling

The gateway returns IGenericResult<T> - always check IsSuccess before accessing Value:

From unit tests DataGatewayServiceTests.cs:125-157:

[Fact]
public async Task Execute_ShouldCallConnectionExecute_WhenConnectionFound()
{
    // Arrange
    var containerMock = new Mock<IStorageContainer>();
    _dataStoreProviderMock
        .Setup(p => p.GetRegisteredContainer("TestContainer"))
        .Returns(GenericResult<IStorageContainer>.Success(containerMock.Object));

    var service = new DataGatewayService(_loggerFactory, _connectionProviderMock.Object, _dataStoreProviderMock.Object, _dataSetProviderMock.Object);
    var commandMock = new Mock<IDataCommand>();
    commandMock.Setup(c => c.ConnectionName).Returns("test-connection");
    commandMock.Setup(c => c.CommandType).Returns("Query");
    commandMock.Setup(c => c.ContainerName).Returns("TestContainer");

    var connectionMock = new Mock<IDataConnection>();
    var expectedResult = GenericResult<string>.Success("test-result");
    connectionMock
        .Setup(c => c.Execute<string>(It.IsAny<IDataCommand>(), It.IsAny<IStorageContainer>(), It.IsAny<CancellationToken>()))
        .ReturnsAsync(expectedResult);

    _connectionProviderMock
        .Setup(p => p.Create("test-connection"))
        .Returns(GenericResult<IDataConnection>.Success(connectionMock.Object));

    // Act
    var result = await service.Execute<string>(commandMock.Object, TestContext.Current.CancellationToken);

    // Assert
    result.IsSuccess.ShouldBeTrue();
    result.Value.ShouldBe("test-result");
    connectionMock.Verify(c => c.Execute<string>(commandMock.Object, containerMock.Object, It.IsAny<CancellationToken>()), Times.Once);
}

Execution Flow

The gateway execution follows this pattern:

  1. Application creates an IDataCommand with ConnectionName and ContainerName
  2. Gateway checks if ContainerName is a registered DataSet (federated query support)
  3. Gateway resolves the container via IDataStoreProvider.GetRegisteredContainer()
  4. Gateway resolves the connection via IDataConnectionProvider.Create()
  5. Gateway delegates to IDataConnection.Execute() with command and container
  6. Connection translates command internally and executes against backend
  7. Result is returned as IGenericResult<T>

From DataGateway.cs:65-95:

public async Task<IGenericResult<T>> Execute<T>(IDataCommand command, CancellationToken cancellationToken = default)
{
    DataGatewayLogger.RoutingCommand(_logger, command.CommandType, command.ConnectionName);

    // Check if containerName is a registered dataset FIRST
    if (_dataSetProvider.IsDataSetRegistered(command.ContainerName))
    {
        DataGatewayLogger.RoutingToDataSet(_logger, command.ContainerName);
        return await ExecuteDataSet<T>(command, cancellationToken).ConfigureAwait(false);
    }

    // Resolve container from IDataStoreProvider
    var containerResult = _dataStoreProvider.GetRegisteredContainer(command.ContainerName);
    if (!containerResult.IsSuccess || containerResult.Value == null)
    {
        var message = DataGatewayLogger.ContainerNotFound(_logger, command.ContainerName);
        return GenericResult<T>.Failure(message);
    }
    var container = containerResult.Value;

    var connectionResult = _connectionProvider.Create(command.ConnectionName);
    if (!connectionResult.IsSuccess || connectionResult.Value == null)
    {
        return GenericResult<T>.Failure(
            DataGatewayLogger.ConnectionRetrievalFailed(_logger, command.ConnectionName));
    }

    var connection = connectionResult.Value;

    return await connection.Execute<T>(command, container, cancellationToken).ConfigureAwait(false);
}

Built-In Translator Pattern

The DataGateway uses the Built-In Translator Pattern where:

  • Gateway is simple: Routes commands to connections, resolves containers
  • Connection owns translator: Each connection type has its own translator
  • Loose coupling: Gateway only knows about IDataConnection, not translation logic

This keeps the gateway minimal while allowing connections to handle their specific translation needs.

Best Practices

Gateway Usage

DO:

  • Inject IDataGateway into services via DI
  • Use configuration for connection names (not hardcoded strings)
  • Check result.IsSuccess before using result.Value
  • Use typed commands (QueryCommand<T>) for type safety

DO NOT:

  • Create DataGateway instances directly
  • Ignore failure results
  • Throw exceptions (use Result pattern)

Testing

For test examples, see DataGatewayServiceTests.cs.

Key test patterns from the test file:

From DataGatewayServiceTests.cs:72-97:

[Fact]
public async Task Execute_ShouldReturnFailure_WhenConnectionNotFound()
{
    // Arrange
    var containerMock = new Mock<IStorageContainer>();
    _dataStoreProviderMock
        .Setup(p => p.GetRegisteredContainer("TestContainer"))
        .Returns(GenericResult<IStorageContainer>.Success(containerMock.Object));

    var service = new DataGatewayService(_loggerFactory, _connectionProviderMock.Object, _dataStoreProviderMock.Object, _dataSetProviderMock.Object);
    var commandMock = new Mock<IDataCommand>();
    commandMock.Setup(c => c.ConnectionName).Returns("test-connection");
    commandMock.Setup(c => c.CommandType).Returns("Query");
    commandMock.Setup(c => c.ContainerName).Returns("TestContainer");

    _connectionProviderMock
        .Setup(p => p.Create("test-connection"))
        .Returns(GenericResult<IDataConnection>.Failure("Connection not found"));

    // Act
    var result = await service.Execute<string>(commandMock.Object, TestContext.Current.CancellationToken);

    // Assert
    result.IsSuccess.ShouldBeFalse();
    result.Messages.ShouldNotBeEmpty();
}

Target Framework

  • .NET Standard 2.0

Dependencies

NuGet Packages:

  • Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions

Project References:

  • FractalDataWorks.Data.Abstractions - IStorageContainer, IFilterExpression
  • FractalDataWorks.Data.DataSets.Abstractions - DataSet configuration
  • FractalDataWorks.Data.DataStores.Abstractions - DataStore configuration
  • FractalDataWorks.Data.DataContainers.Abstractions - Container schema
  • FractalDataWorks.Results - Result pattern
  • FractalDataWorks.Services.Abstractions - Base service interfaces
  • FractalDataWorks.Services.Connections.Abstractions - IDataConnection, IDataConnectionProvider
  • FractalDataWorks.Services.SecretManagers.Abstractions - Secret management
  • FractalDataWorks.Services.Abstractions - Registration options
  • FractalDataWorks.Messages - Message templates
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on FractalDataWorks.Services.Data.Abstractions:

Package Downloads
FractalDataWorks.Calculations.Abstractions

Development tools and utilities for the FractalDataWorks ecosystem. Build:

FractalDataWorks.Calculations

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
Loading failed