IFY.Phorm.SqlClient 1.7.3

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

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

Build & Test Code Coverage Mutation testing badge Code Quality

A full 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 RL
subgraph Database
    D[(Data)]
    V((vw))
    SP((sp))
end
subgraph Application
    O[DTO]
    I[/Interface/]
end

D -->|Get| O;
D --> V -->|Get| O;
SP -->|From.Get| O;
O -.->|Call/From| I --> SP --> D;

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 = session.Get<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 = session.Call<ISaveData>(newItem); // Procedure dbo.usp_SaveData

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

Syntax overview

IPhormSession
    // Calling a contract
    int Call(string contractName, object? args = null);
    int Call<TActionContract>(object? args = null);
    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)
    TResult? Get<TResult>(object? args = null);
    Task<TResult?> GetAsync<TResult>(object? args = null, CancellationToken cancellationToken = CancellationToken.None);

    // Fetching from a named procedure
    From(string contractName, object? args = null)
        TResult? Get<TResult>();
        Task<TResult?> GetAsync<TResult>(CancellationToken cancellationToken = CancellationToken.None);
        // Resultset filtering
        Where<TEntity>(Expression<Func<TEntity, bool>> predicate)
            IEnumerable<TEntity> GetAll();
            Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = CancellationToken.None);
    
    // Fetching from a contract definition (procedure, table, view)
    From<TActionContract>(object? args = null)
        TResult? Get<TResult>();
        Task<TResult?> GetAsync<TResult>(CancellationToken cancellationToken = CancellationToken.None);
        // Resultset filtering
        Where<TEntity>(Expression<Func<TEntity, bool>> predicate)
            IEnumerable<TEntity> GetAll();
            Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = CancellationToken.None);
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  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 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

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.7.3 233 8/25/2023
1.7.1 251 4/9/2023
1.7.0 271 3/30/2023
1.6.1 285 3/28/2023
1.5.3 379 11/20/2022

v1.7.3
- #45: Fix regression of bug

v1.7.2.1
- ResultsetAttribute does not require selector to be specified
- Updated all dependencies

v1.7.2
- #45: Fix transaction commands not being attached

v1.7.1
- #43: Fix enum parsing not supporting non-int values

v1.7.0
- #38: Lazy resolution of results
- #38: Pre-resolution filtering of entity resultsets

v1.6.1
- #39: Fix transformations occuring before literal properties

v1.6.0
- Breaking change to IEncryptor
- #34: Allow decryptor to be chosen using encrypted data

v1.5.3
- #32: Contract out parameter fails if anon object doesn't define it

v1.5.2
- #29: Interface implemented properties not resolving on call contract

v1.5.1
- #24: Support DateOnly
- #19: Dynamic removal of members

v1.5.0.1
- Minor internal changes