FractalDataWorks.Services.Data.Abstractions
0.4.0-preview.6
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
<PackageReference Include="FractalDataWorks.Services.Data.Abstractions" Version="0.4.0-preview.6" />
<PackageVersion Include="FractalDataWorks.Services.Data.Abstractions" Version="0.4.0-preview.6" />
<PackageReference Include="FractalDataWorks.Services.Data.Abstractions" />
paket add FractalDataWorks.Services.Data.Abstractions --version 0.4.0-preview.6
#r "nuget: FractalDataWorks.Services.Data.Abstractions, 0.4.0-preview.6"
#:package FractalDataWorks.Services.Data.Abstractions@0.4.0-preview.6
#addin nuget:?package=FractalDataWorks.Services.Data.Abstractions&version=0.4.0-preview.6&prerelease
#tool nuget:?package=FractalDataWorks.Services.Data.Abstractions&version=0.4.0-preview.6&prerelease
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:
- Application creates an
IDataCommandwithConnectionNameandContainerName - Gateway checks if
ContainerNameis a registered DataSet (federated query support) - Gateway resolves the container via
IDataStoreProvider.GetRegisteredContainer() - Gateway resolves the connection via
IDataConnectionProvider.Create() - Gateway delegates to
IDataConnection.Execute()with command and container - Connection translates command internally and executes against backend
- 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
IDataGatewayinto services via DI - Use configuration for connection names (not hardcoded strings)
- Check
result.IsSuccessbefore usingresult.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
Related Packages
- FractalDataWorks.Services.Data - DataGatewayService implementation
- FractalDataWorks.Commands.Data - QueryCommand, InsertCommand, etc.
- FractalDataWorks.Services.Connections - Connection implementations
| Product | Versions 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. |
-
.NETStandard 2.0
- FractalDataWorks.Collections (>= 0.4.0-preview.6)
- FractalDataWorks.Data.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Data.DataContainers.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Data.DataSets.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Data.DataStores.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Messages (>= 0.4.0-preview.6)
- FractalDataWorks.Results (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Connections.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.SecretManagers.Abstractions (>= 0.4.0-preview.6)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.1)
- System.Collections.Immutable (>= 10.0.1)
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 |
|---|