Skip to content

russlank/XpressData

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

XpressData

A lightweight, high-performance micro-ORM for .NET that provides a fluent API for building type-safe SQL queries and mapping entities to database tables.

License: MIT NuGet Buy Me A Coffee

Features

  • 🚀 High Performance: Minimal overhead with direct ADO.NET access
  • 🧵 Thread-Safe: Designed for concurrent operations in multi-threaded applications
  • 🔒 Type-Safe Queries: Compile-time type checking for SQL expressions
  • 🔄 Fluent API: Intuitive expression builder for complex queries
  • Full Async/Await Support: All database operations have async variants with cancellation token support
  • ⚙️ Flexible Mapping: Attribute-based or fluent entity-to-table mapping
  • ⏱️ Transaction Support: Full transaction management with commit/rollback
  • 📊 Multiple Data Types: Support for all common SQL Server data types
  • 🎯 Multi-Targeting: Supports .NET 6.0 through .NET 10.0
  • 📚 Fully Documented: Comprehensive XML documentation for all public APIs

What XpressData Is

XpressData is a micro-ORM designed for developers who want:

  • Fine-grained control over SQL queries
  • Strong typing without the complexity of full ORMs
  • High performance with minimal abstraction
  • Easy integration with existing SQL Server databases

What XpressData Is NOT

XpressData is not a replacement for Entity Framework or other full-featured ORMs. It does not:

  • Provide automatic migration support
  • Implement lazy loading or change tracking
  • Generate database schemas automatically
  • Support multiple database providers (SQL Server only)

Installation

Install via NuGet Package Manager:

dotnet add package XpressData

Or via Package Manager Console:

Install-Package XpressData

Quick Start

1. Define Your Entity

public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string? Email { get; set; }
    public DateTime CreatedAt { get; set; }
}

2. Create an Entity Map

using XpressData.Mapping;
using XpressData.Mapping.FieldTypes;

public class UserMap : EntityMap<User>
{
    public FieldMap Id { get; private set; } = null!;
    public FieldMap Name { get; private set; } = null!;
    public FieldMap Email { get; private set; } = null!;
    public FieldMap CreatedAt { get; private set; } = null!;

    public UserMap() : base(null)
    {
        InitializeMap();
    }

    public override void InitializeMap()
    {
        base.InitializeMap();
        
        PhysicalTableName = "Users";
        
        Id = new FieldMap(this, new FieldTypeInteger(), "Id", "id", isPK: true);
        Name = new FieldMap(this, new FieldTypeString(100), "Name", "name");
        Email = new FieldMap(this, new FieldTypeString(255), "Email", "email", isNullable: true);
        CreatedAt = new FieldMap(this, new FieldTypeDateTime(), "CreatedAt", "created_at");
    }
}

3. Configure Dependency Injection

// In Program.cs or Startup.cs
services.AddXpressData(Configuration.GetSection("XpressData"));
// In appsettings.json
{
  "XpressData": {
    "Server": "localhost",
    "Database": "MyDatabase",
    "UserId": "sa",
    "Password": "YourPassword",
    "TrustServerCertificate": true
  }
}

4. Use the Database Connection

using XpressData.Datalayer;
using XpressData.Expressions;

public class UserService
{
    private readonly IDatabase _database;
    private readonly UserMap _userMap;

    public UserService(IDatabase database)
    {
        _database = database;
        _userMap = new UserMap();
    }

    public User[] GetActiveUsers()
    {
        using var connection = _database.CreateConnection();
        connection.Open();

        // Build type-safe filter expression
        IExpressionString nameField = Builder.Field(_userMap.Name);
        var filter = Builder.IsNotNull(nameField);

        // Execute query
        var users = _userMap.Get(connection, filterExpression: filter);
        
        connection.Close();
        return users;
    }
}

Examples

Building Expressions

XpressData uses a type-safe expression builder. When comparing values, cast to the appropriate interface:

// Numeric comparison
IExpressionNumeric idField = Builder.Field(userMap.Id);
IExpressionNumeric idValue = Builder.Value(42);
var filter = Builder.Equal(idField, idValue);

// String comparison
IExpressionString nameField = Builder.Field(userMap.Name);
IExpressionString pattern = Builder.Value("%John%");
var likeFilter = Builder.Like(nameField, pattern);

// Combining conditions
var combinedFilter = Builder.And(filter, likeFilter);

Available Expression Interfaces

Interface Use Case
IExpressionNumeric int, long, decimal comparisons
IExpressionString String comparisons, LIKE
IExpressionGuid GUID comparisons
IExpressionDate Date-only comparisons
IExpressionDateTime DateTime comparisons
IExpressionLogical AND, OR, NOT operations
IExpressionComperable IN, NOT IN operations

Transactions

using var connection = _database.CreateConnection();
connection.Open();

try
{
    connection.BeginTransaction();
    
    _userMap.Insert(connection, newUser);
    _orderMap.Insert(connection, newOrder);
    
    connection.Commit();
}
catch
{
    connection.Rollback();
    throw;
}
finally
{
    connection.Close();
}

Ordering Results

// Order by Name ascending, then Id descending
var orderBy = Builder.OrderBy(userMap.Name, EOrder.Asc,
    Builder.OrderBy(userMap.Id, EOrder.Desc));

var users = userMap.Get(connection, orderByInfo: orderBy);

IN Clause

IExpressionComperable idField = Builder.Field(userMap.Id);
var values = Builder.Values(new[] { 1, 2, 3, 4, 5 });
var inFilter = Builder.In(idField, values);

var users = userMap.Get(connection, filterExpression: inFilter);

Pagination

var users = userMap.Get(
    connection,
    orderByInfo: Builder.OrderBy(userMap.Id),
    limit: 10,
    offset: 20);

Async Operations

All database operations have async equivalents with full cancellation token support:

// Async with using declaration
await using var connection = new DatabaseConnection(dbInfo);

// Async SELECT
var result = await connection.SelectAsync(new Query("SELECT * FROM Users"));

// Async EntityMap operations
var users = await userMap.GetAsync(connection, filterExpression: filter);
var user = await userMap.GetByPrymaryKeyAsync(connection, 1);
await userMap.InsertAsync(connection, newUser);
await userMap.UpdateAsync(connection, existingUser);
await userMap.DeleteAsync(connection, userToDelete);

// With cancellation token
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var users = await userMap.GetAsync(connection, cancellationToken: cts.Token);

Supported Field Types

FieldType Class SQL Type .NET Type
FieldTypeInteger [int] int
FieldTypeBigInt [bigint] long
FieldTypeString(length) [varchar](n) string
FieldTypeFixedString(length) [char](n) string
FieldTypeGuid [uniqueidentifier] Guid
FieldTypeBoolean [bit] bool
FieldTypeDateTime [datetime] DateTime
FieldTypeDate [date] DateTime
FieldTypeNumeric(p, s) [numeric](p,s) decimal
FieldTypeBinary(length) [varbinary](n) byte[]
FieldTypeFixedBinary(length) [binary](n) byte[]

Testing

XpressData includes comprehensive unit and integration tests.

Run All Tests

dotnet test

Run Unit Tests Only

dotnet test --filter "Category!=Integration"

Run Integration Tests Only

Integration tests require SQL Server LocalDB:

dotnet test --filter "Category=Integration"

Documentation

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Russlan Kafri
Company: Digixoil

Support

For issues, questions, or suggestions:

  • Open an issue on GitHub
  • Check existing documentation in the /doc folder
  • Review XML documentation in source code

Made with ❤️ by Digixoil

About

A lightweight, high-performance micro-ORM for .NET that provides a fluent API for building type-safe SQL queries and mapping entities to database tables.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages