Codebelt

Cuemon.Data

Provider-agnostic data access abstractions, streaming readers, and query helpers for relational, DSV, and XML data sources.

.NET 10.0 / .NET 9.0 MIT v10.5.3 65,478 downloads

Overview

Cuemon.Data extends System.Data with provider-agnostic command abstractions, forward-only readers, and row materialization helpers that let consumers work with relational, DSV, and XML shaped data through the same core model. Built on Cuemon.Core, it combines executable statements, typed value conversion, and IDataReader-style access so package consumers can move between database results and file-backed payloads without changing the surrounding workflow.

The package also covers the edges around that workflow. It includes base classes for provider-specific command execution and query generation, helpers for parameter-safe IN clauses, and watcher primitives that monitor relational result sets by hashing the rows returned from a query.

Key APIs

DataManager is the provider-facing execution shell for the package. You implement GetDbCommand(DataStatement) and Clone(), then reuse its synchronous and asynchronous helpers for non-query execution, scalar conversion, existence checks, string materialization, and IDataReader access while DataManagerOptions controls connection lifetime and preferred reader behavior.

DataStatement packages the SQL text together with CommandType, timeout, and parameters. It also supports implicit conversion from string, so callers can move from a literal statement to a configured command object only when they need custom options.

DsvDataReader turns delimiter-separated text into a forward-only IDataReader. It can read the header from the stream or accept one explicitly, applies value parsing through ParserFactory.FromValueType, exposes typed getters from DataReader<TRead>, validates the expected column count for every row, and supports both Read() and ReadAsync().

XmlDataReader performs the same IDataReader translation for XML. It walks an XmlReader, projects attributes and text nodes into the current row, tracks element depth, increments RowCount only when a row was actually produced, and disposes the wrapped reader when the data reader is disposed.

DataTransfer converts any open IDataReader into DataTransferRowCollection and DataTransferColumnCollection. That snapshot model gives consumers indexed, named, and exact-type access through DataTransferRow, which is useful when downstream code needs table-like inspection without staying attached to the live reader.

InOperator<T> is the package's safe path for building parameterized IN clause fragments. Derived implementations decide how each value becomes an IDbDataParameter, while ToSafeResult() returns both the generated parameter tokens and the matching parameter collection through InOperatorResult.

QueryBuilder is the base abstraction for generating T-SQL statements from table and column definitions. It exposes fragment encoding helpers, read-limit and dirty-read switches, automatic table and column encapsulation flags, and append helpers for derived query builders.

DatabaseWatcher monitors a relational result set by executing a reader factory, hashing each row into a checksum, and raising the inherited change signal when the checksum changes. Pair it with DatabaseDependency when you want one or more watchers created lazily and attached to the dependency model only when monitoring starts.

Basic usage

using System;
using System.Globalization;
using System.IO;
using System.Text;
using Cuemon.Data;
using Codebelt.Extensions.Xunit;
using Xunit;

namespace Contoso.Data.Tests;

public class DsvShipmentImportTest : Test
{
    public DsvShipmentImportTest(ITestOutputHelper output) : base(output)
    {
    }

    [Fact]
    public void ShouldMaterializeShipmentRowsFromDsv()
    {
        const string dsv = """
OrderId;Quantity;Warehouse
ORD-1001;12;North
ORD-1002;4;Overflow
""";

        using var stream = new MemoryStream(Encoding.UTF8.GetBytes(dsv));
        using var reader = new DsvDataReader(new StreamReader(stream), setup: o =>
        {
            o.Delimiter = ";";
            o.FormatProvider = CultureInfo.InvariantCulture;
        });

        var rows = DataTransfer.GetRows(reader);

        Assert.Equal(2, rows.Count);
        Assert.Equal(12, Convert.ToInt32(rows[0]["Quantity"], CultureInfo.InvariantCulture));
        Assert.Equal("Overflow", Convert.ToString(rows[1]["Warehouse"], CultureInfo.InvariantCulture));
        TestOutput.WriteLine(rows[0].ToString());
    }
}

Use this pattern when a delimited export needs to be consumed through IDataReader semantics instead of a one-off parser. It matters because DsvDataReader validates row shape, applies configured value parsing, and lets downstream code materialize the result into reusable row objects.

Installation

dotnet add package Cuemon.Data

Usage guidance

Adopt Cuemon.Data when you need one package to cover statement objects, provider-specific execution shells, DSV or XML readers, row materialization, or query helpers that still speak in System.Data terms. If you only need raw ADO.NET commands and data readers, stay with the framework APIs, and if you are targeting Microsoft SQL Server specific integrations choose Cuemon.Data.SqlClient instead of building directly on the base abstractions.

Family packages