IFY.Phorm.Core 2.3.1

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

<div align="center">

Cham

</div>

Pho/rm - The Procedure-heavy object-relational mapping framework

Build & Test Code Coverage Mutation testing badge Code Quality

A micro-O/RM, focused on strong separation between the data structures and the business entity representation.

See our ethos for how and why Pho/rm is different to other O/RMs.

The wiki contains lots of useful examples of the various features, as well as a getting started guide.

Pho/rm supports:

Packages
IFY.Phorm.Core NuGet Version NuGet Downloads
IFY.Phorm.SqlClient NuGet Version NuGet Downloads

Driving principals

The are many, brilliant O/RM frameworks available using different paradigms for database interaction.
Many of these allow for rapid adoption by strongly-coupling to the storage schema at the expense of control over the efficiency of the query and future structural mutability.
As such solutions grow, it can become quickly difficult to evolve the underlying structures as well as to improve the way the data is accessed and managed.

Pho/rm was designed to provide a small and controlled surface between the business logic layer and the data layer by pushing the shaping of data to the data provider and encouraging the use of discrete contracts.
Our goal is to have a strongly-typed data surface and allow for a mutable physical data structure, where responsibility of the layers can be strictly segregated.

With this approach, the data management team can provide access contracts to meet the business logic requirements, which the implementing team can rely on without concern over the underlying structures and query efficiency.

flowchart
    I[/Interface/]
    O[DTO]
    T[Table]
    V((vw))
    SP((sp))

    I --> SP
    V -->|Get| O
    SP -->|From.Get| O
    T -->|Get| O
    O -.->|Call/From| I
    T --> V
    T <--> SP

    subgraph Application
        O
        I
    end
    subgraph Database
        T
        V
        SP
    end

Common example

For typical entity CRUD support, a Pho/rm solution would require a minimum of:

  1. Existing tables in the data source
  2. A POCO to represent the entity (DTO); ideally with a contract for each database action
  3. A stored procedure to fetch the entity
  4. At least one stored procedure to handle create, update, delete (though, ideally, one for each)

A simple Pho/rm use would have the structure:

CREATE TABLE [dbo].[Data] (
    [Id] BIGINT NOT NULL PRIMARY KEY,
    [Key] NVARCHAR(50) NOT NULL UNIQUE,
    [Value] NVARCHAR(256) NULL
)

CREATE PROCEDURE [dbo].[usp_SaveData] (
    @Key NVARCHAR(50),
    @Value NVARCHAR(256),
    @Id BIGINT = NULL OUTPUT
) AS
    SET NOCOUNT ON
    INSERT INTO [dbo].[Data] ([Key], [Value])
        SELECT @Key, @Value
    SET @Id = SCOPE_IDENTITY()
RETURN 1 -- Success
// DTO and contracts
[PhormContract(Name = "Data")] // Name of underlying table (optional)
class DataItem : ISaveData
{
    public long Id { get; set; }
    public string Key { get; set; } = string.Empty;
    public string? Value { get; set; }
}
interface ISaveData : IPhormContract
{
    long Id { set; } // Output
    string Key { get; }
    string? Value { get; }
}

// Configure Pho/rm session to SQL Server
IPhormSession session = new SqlPhormSession(connectionString);

// Get all existing records from the table
DataItem[] allData = await session.GetAsync<DataItem[]>()!; // Table dbo.Data

// Add a new record to the table, getting back the new id
var newItem = new { Id = ContractMember.Out<long>(), Key = "Name", Value = "T Ester" };
int result = await session.CallAsync<ISaveData>(newItem); // Procedure dbo.usp_SaveData

DataItem? itemById = await session.GetAsync<DataItem>(new { Id = newItem.Id }); // Table dbo.Data
DataItem? itemByKey = await session.GetAsync<DataItem>(new { Key = "Name" }); // Table dbo.Data

Syntax overview

IPhormSession
    // Calling a contract
    Task<int> CallAsync(string contractName, object? args = null, CancellationToken cancellationToken = CancellationToken.None);
    Task<int> CallAsync<TActionContract>(object? args = null, CancellationToken cancellationToken = CancellationToken.None);

    // Fetching from a DTO definition (table, view)
    Task<TResult?> GetAsync<TResult>(object? args = null, CancellationToken cancellationToken = CancellationToken.None);

    // Fetching from a named procedure
    From(string contractName, object? args = null)
        Task<TResult?> GetAsync<TResult>(CancellationToken cancellationToken = CancellationToken.None);
        // Resultset filtering
        Where<TEntity>(Expression<Func<TEntity, bool>> predicate)
            Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = CancellationToken.None);
    
    // Fetching from a contract definition (procedure, table, view)
    From<TActionContract>(object? args = null)
        Task<TResult?> GetAsync<TResult>(CancellationToken cancellationToken = CancellationToken.None);
        // Resultset filtering
        Where<TEntity>(Expression<Func<TEntity, bool>> predicate)
            Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = CancellationToken.None);

Versioning

Pho/rm uses Semantic Versioning where provider implementations (e.g. SQL Server) will use the same major and minor versions as the core package, but may have a different patch version.
For example, the provider package patch version will be incremented when there is a fix or change in the provider implementation (or core), but the core package remains unchanged.

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 is compatible.  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 netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen 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 (1)

Showing the top 1 NuGet packages that depend on IFY.Phorm.Core:

Package Downloads
IFY.Phorm.SqlClient

SqlClient implementation of the Procedure-heavy object-relational mapping framework.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.3.1 139 5/11/2026
2.3.0 170 1/21/2026
2.2.0 166 1/8/2026
2.1.0 485 12/8/2025
2.0.0 257 9/24/2025
1.7.4 252 9/23/2025
1.7.3 299 8/25/2023
1.7.2.1 304 8/21/2023
1.7.2 370 4/21/2023
1.7.1 310 4/9/2023
1.7.0 323 3/30/2023
1.6.1 323 3/28/2023
1.6.0 425 11/23/2022
1.5.3 439 11/20/2022
1.5.2 460 11/14/2022
1.5.1 450 11/11/2022
1.5.0.1 465 11/10/2022

v2.3.1
- #60: WithContext maintains session configuration
v2.3.0
- #57: Added support for session context data
v2.2.0
- #49: Added support for record primary constructors
v2.1.0
- #47: Support read-only application intent per contract
v2.0.0
- #52: Removed non-async methods