Linka 1.0.1

dotnet add package Linka --version 1.0.1
                    
NuGet\Install-Package Linka -Version 1.0.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="Linka" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Linka" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Linka" />
                    
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 Linka --version 1.0.1
                    
#r "nuget: Linka, 1.0.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 Linka@1.0.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=Linka&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Linka&version=1.0.1
                    
Install as a Cake Tool

Linka ORM

A modern, type-safe Object-Relational Mapping (ORM) framework for .NET with PostgreSQL, designed for high performance and developer productivity.

Features

  • ๐Ÿš€ Type-Safe: Strongly typed models with compile-time validation
  • ๐ŸŽฏ Field-Based Architecture: Rich field types with built-in validation
  • ๐Ÿ”„ Change Tracking: Automatic detection of field modifications
  • ๐Ÿงช Testing Framework: Built-in test utilities with database mocking
  • ๐Ÿ” Query Builder: Fluent API for complex database operations
  • ๐Ÿ“Š Schema Management: Automatic database schema generation and migration
  • ๐Ÿ”’ Validation: Comprehensive field validation with custom validators
  • ๐ŸŽจ Flexible: Support for enums, custom types, and complex relationships

Quick Start

1. Define Your Models

public class UserModel() : Model
{
    [Key]
    [Unique]
    [FullText]
    public IdDbField ID { get; } = new();

    [FullText]
    public NameDbField Name { get; } = new();

    [FullText]
    [Unique]
    public EmailDbField Email { get; } = new();

    [FullText]
    public PhoneDbField Phone { get; } = new();

    public enum RankEnum
    {
        User,
        Admin
    }

    public EnumDbField<RankEnum> Rank { get; } = new();

    [Unique]
    [NotRequired]
    public HashDbField Session { get; } = new();

    public TextDbField Password { get; } = new();

    [NotRequired] // Navigation Field Property
    public IdDbField CartToken { get; } = new();

    public DateDbField Created { get; } = new();

    public BooleanDbField Verified { get; } = new();
    public BooleanDbField Login { get; } = new();
    public PriceDbField<Gbp> Credit { get; } = new();

    [PkNavigationList(nameof(IpAddressModel.UserID))]
    public List<IpAddressModel> IpAddresses = null!;

    public UserModel(
        string name,
        string email,
        string phone,
        RankEnum rankEnum,
        string password,
        string? cartToken,
        bool verified,
        bool login,
        int credit
    ) : this()
    {
        Name.Value(name);
        Email.Value(email);
        Phone.Value(phone);
        Rank.Value(rankEnum);
        Password.Value(password);
        CartToken.Value(cartToken);
        Created.SetNow();
        Verified.Value(verified);
        Login.Value(login);
        Credit.Value(credit);
    }
}

2. Create Database Schema

[method: Enum<UserModel.RankEnum>]
[method: Model<UserModel>]
[method: Model<IpAddressModel>]
public class UserSchema() : Schema("User");

3. Basic Operations

// Create a new user using constructor
var model1 = new UserModel(
    "John",
    "johndoe@example.com",
    "1234567890",
    UserModel.RankEnum.User,
    "password",
    null,
    true,
    false,
    100
);
model1.ID.Value("AAAAAAAAAA");

// Insert into database
using var db = new DbService<UserSchema>();
db.Insert(model1);
db.SaveChanges();

// Query single user
var user = db.Get<UserModel>(u => u.ID == "AAAAAAAAAA");
var userOrNull = db.GetOrNull<UserModel>(u => u.ID == "NONEXISTENT");

// Query multiple users
var adminUsers = db.GetMany<UserModel>(u => u.Rank == UserModel.RankEnum.Admin).Load();
var userCount = db.GetMany<UserModel>(u => u.Verified == true).Count();

// Update user fields directly
var foundUser = db.Get<UserModel>(u => u.ID == "AAAAAAAAAA");
foundUser.Name.Value("John Updated");
foundUser.Rank.Value(UserModel.RankEnum.Admin);
// Changes are automatically tracked

// Delete user
db.Delete<UserModel>(u => u.ID == "AAAAAAAAAA");

Database Operations

Querying

using var db = new DbService<UserSchema>();

// Single record queries
var user = db.Get<UserModel>(u => u.Email == "johndoe@example.com");
var userOrNull = db.GetOrNull<UserModel>(u => u.ID == "AAAAAAAAAA");

// Multiple record queries
var getManyExpression = db.GetMany<UserModel>(u => u.Verified == true);
var users = getManyExpression.Load(); // Execute and get results
var count = getManyExpression.Count(); // Get count without loading data

// Complex queries
var adminUsers = db.GetMany<UserModel>(u => u.Rank == UserModel.RankEnum.Admin).Load();
var verifiedUsers = db.GetMany<UserModel>(u => u.Verified == true).Load();

CRUD Operations

using var db = new DbService<UserSchema>();

// Create
var user = new UserModel(
    "Alice",
    "alice@example.com",
    "0987654321",
    UserModel.RankEnum.Admin,
    "securePass123",
    null,
    true,
    true,
    250
);
user.ID.Value("BBBBBBBBBB");
db.Insert(user);
db.SaveChanges();

// Read
var foundUser = db.Get<UserModel>(u => u.ID == "BBBBBBBBBB");

// Update (fields are automatically tracked)
foundUser.Name.Value("Alice Updated");
foundUser.Credit.Value(300);

// Delete
db.Delete<UserModel>(u => u.ID == "BBBBBBBBBB");

Testing

Linka includes a comprehensive testing framework with database mocking:

Test Setup

[Fixtures<UserModelFixture>]
[Fixtures<IpAddressFixture>]
public class UserServiceTests
{
    [Test]
    public void Get_UserModel_ReturnsExpected()
    {
        using var db = new DbService<UserSchema>();
        var model = db.Get<UserModel>(u => u.ID == "AAAAAAAAAA");
        Ensure.Equal("John", model.Name.Value());
    }
}

Fixtures

public class UserModelFixture : Fixture<UserSchema>, IFixture
{
    public override void Inject()
    {
        var model1 = new UserModel(
            "John",
            "johndoe@example.com",
            "1234567890",
            UserModel.RankEnum.User,
            "password",
            null,
            true,
            false,
            100
        );
        model1.ID.Value("AAAAAAAAAA");

        using var db = new DbService<UserSchema>();
        db.Insert(model1);
        db.SaveChanges();
    }
}

Multiple Fixtures

[Fixtures<UserModelFixture>]
[Fixtures<IpAddressFixture>]
public class IntegrationTests
{
    // All fixtures will be applied before tests run
}

Field Operations

Setting Values

user.Name.Value("John Doe");
user.Created.SetNow();  // Set to current date
user.ID.Value("AAAAAAAAAA"); // Set specific ID

Accessing Values

string name = user.Name.StringValue();  // Get as string
object nameObj = user.Name.ObjectValue(); // Get as typed object
string userName = user.Name.Value();    // Get typed value

Validation

if (user.Email.IsValid(out string message))
{
    // Email is valid
}
else
{
    Console.WriteLine($"Invalid email: {message}");
}

Best Practices

  1. Use constructors for creating models with required fields
  2. Use GetOrNull when records might not exist
  3. Use GetMany().Count() for counting without loading data
  4. Use GetMany().Load() when you need the actual records
  5. Use fixtures for comprehensive test data setup
  6. Call SaveChanges() after inserts or updates to commit transactions

Requirements

  • .NET 9.0 or later

Installation

# Install via NuGet
dotnet add package Linka.ORM

# Or clone and build from source
git clone https://github.com/webamoki/linka-orm.git
cd linka-orm
dotnet build
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 106 9/5/2025
1.0.0 110 9/5/2025