FluentCommand 13.4.1
dotnet add package FluentCommand --version 13.4.1
NuGet\Install-Package FluentCommand -Version 13.4.1
<PackageReference Include="FluentCommand" Version="13.4.1" />
<PackageVersion Include="FluentCommand" Version="13.4.1" />
<PackageReference Include="FluentCommand" />
paket add FluentCommand --version 13.4.1
#r "nuget: FluentCommand, 13.4.1"
#:package FluentCommand@13.4.1
#addin nuget:?package=FluentCommand&version=13.4.1
#tool nuget:?package=FluentCommand&version=13.4.1
FluentCommand
Fluent Wrapper for DbCommand.
| Package | Version | 
|---|---|
| FluentCommand | |
| FluentCommand.SqlServer | |
| FluentCommand.Json | 
Download
The FluentCommand library is available on nuget.org via package name FluentCommand.
To install FluentCommand, run the following command in the Package Manager Console
PM> Install-Package FluentCommand
More information about NuGet package available at https://nuget.org/packages/FluentCommand
Features
- Fluent wrapper over DbConnection and DbCommand
- Callback for parameter return values
- Automatic handling of connection state
- Caching of results
- Automatic creating of entity from DataReader via Dapper
- Create Dynamic objects from DataReader via Dapper
- Handles multiple result sets
- Basic SQL query builder
- Source Generate DataReader
Configuration
Configuration for SQL Server
IDataConfiguration dataConfiguration  = new DataConfiguration(
    SqlClientFactory.Instance, 
    ConnectionString
);
Register with dependency injection
services.AddFluentCommand(builder => builder
    .UseConnectionString(ConnectionString)
    .UseSqlServer()
);
Register using a connection name from the appsettings.json
services.AddFluentCommand(builder => builder
    .UseConnectionName("Tracker")
    .UseSqlServer()
);
{
  "ConnectionStrings": {
    "Tracker": "Data Source=(local);Initial Catalog=TrackerTest;Integrated Security=True;TrustServerCertificate=True;"
  }
}
Register for PostgreSQL
services.AddFluentCommand(builder => builder
    .UseConnectionName("Tracker")
    .AddProviderFactory(NpgsqlFactory.Instance)
    .AddPostgreSqlGenerator()
);
Example
Query all users with email domain. Entity is automatically created from DataReader.
string email = "%@battlestar.com";
string sql = "select * from [User] where EmailAddress like @EmailAddress";
var session = configuration.CreateSession();
var user = await session
    .Sql(sql)
    .Parameter("@EmailAddress", email)
    .QuerySingleAsync(r => new User
    {
        Id = r.GetGuid("Id"),
        EmailAddress = r.GetString("EmailAddress"),
        IsEmailAddressConfirmed = r.GetBoolean("IsEmailAddressConfirmed"),
        DisplayName = r.GetString("DisplayName"),
        PasswordHash = r.GetString("PasswordHash"),
        ResetHash = r.GetString("ResetHash"),
        InviteHash = r.GetString("InviteHash"),
        AccessFailedCount = r.GetInt32("AccessFailedCount"),
        LockoutEnabled = r.GetBoolean("LockoutEnabled"),
        LockoutEnd = r.GetDateTimeOffsetNull("LockoutEnd"),
        LastLogin = r.GetDateTimeOffsetNull("LastLogin"),
        IsDeleted = r.GetBoolean("IsDeleted"),
        Created = r.GetDateTimeOffset("Created"),
        CreatedBy = r.GetString("CreatedBy"),
        Updated = r.GetDateTimeOffset("Updated"),
        UpdatedBy = r.GetString("UpdatedBy"),
        RowVersion = r.GetBytes("RowVersion"),
    });
Execute a stored procedure with out parameters
Guid userId = Guid.Empty;
int errorCode = -1;
var username = "test." + DateTime.Now.Ticks;
var email = username + "@email.com";
var session = configuration.CreateSession();
var result = session
    .StoredProcedure("[dbo].[aspnet_Membership_CreateUser]")
    .Parameter("@ApplicationName", "/")
    .Parameter("@UserName", username)
    .Parameter("@Password", "T@est" + DateTime.Now.Ticks)
    .Parameter("@Email", email)
    .Parameter("@PasswordSalt", "test salt")
    .Parameter<string>("@PasswordQuestion", null)
    .Parameter<string>("@PasswordAnswer", null)
    .Parameter("@IsApproved", true)
    .Parameter("@CurrentTimeUtc", DateTime.UtcNow)
    .Parameter("@UniqueEmail", 1)
    .Parameter("@PasswordFormat", 1)
    .ParameterOut<Guid>("@UserId", p => userId = p)
    .Return<int>(p => errorCode = p)
    .Execute();
Query for user by email address. Also return Role and Status entities.
string email = "kara.thrace@battlestar.com";
string sql = "select * from [User] where EmailAddress = @EmailAddress; " +
             "select * from [Status]; " +
             "select * from [Priority]; ";
User user = null;
List<Status> status = null;
List<Priority> priorities = null;
var session = configuration.CreateSession();
session
    .Sql(sql)
    .Parameter("@EmailAddress", email)
    .QueryMultiple(q =>
    {
        user = q.QuerySingle<User>();
        status = q.Query<Status>().ToList();
        priorities = q.Query<Priority>().ToList();
    });
Query Builder
Build SQL statements with the query builder. Query builder uses the DataAnnotations Schema attributes to extract table and column information.
var session = configuration.CreateSession();
string email = "kara.thrace@battlestar.com";
var user = await session
    .Sql(builder => builder
        .Select<User>() // table name comes from type
        .Where(p => p.EmailAddress, email)
    )
    .QuerySingleAsync<User>();
Count query
string email = "kara.thrace@battlestar.com";
var count = await session
    .Sql(builder => builder
        .Select<User>()
        .Count()
        .Where(p => p.EmailAddress, email)
    )
    .QueryValueAsync<int>();
Insert statement
var id = Guid.NewGuid();
var userId = await session
    .Sql(builder => builder
        .Insert<User>()
        .Value(p => p.Id, id)
        .Value(p => p.EmailAddress, $"{id}@email.com")
        .Value(p => p.DisplayName, "Last, First")
        .Value(p => p.FirstName, "First")
        .Value(p => p.LastName, "Last")
        .Output(p => p.Id) // return key as output value
        .Tag() // add comment tag to query
    )
    .QueryValueAsync<Guid>();
Update statement
var updateId = await session
    .Sql(builder => builder
        .Update<User>()
        .Value(p => p.DisplayName, "Updated Name")
        .Output(p => p.Id)
        .Where(p => p.Id, id)
        .Tag()
    )
    .QueryValueAsync<Guid>();
Delete statement
var deleteId = await session
    .Sql(builder => builder
        .Delete<User>()
        .Output(p => p.Id)
        .Where(p => p.Id, id)
        .Tag()
    )
    .QueryValueAsync<Guid>();
Source Generator
The project supports generating a DbDataReader from a class via an attribute.  Add the TableAttribute to a class to generate the needed extension methods.
[Table("Status", Schema = "dbo")]
public class Status
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int DisplayOrder { get; set; }
    public bool IsActive { get; set; }
    public DateTimeOffset Created { get; set; }
    public string CreatedBy { get; set; }
    public DateTimeOffset Updated { get; set; }
    public string UpdatedBy { get; set; }
    [ConcurrencyCheck]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    [DataFieldConverter(typeof(ConcurrencyTokenHandler))]
    public ConcurrencyToken RowVersion { get; set; }
    [NotMapped]
    public virtual ICollection<Task> Tasks { get; set; } = new List<Task>();
}
Extension methods are generated to materialize data command to entities
string email = "kara.thrace@battlestar.com";
string sql = "select * from [User] where EmailAddress = @EmailAddress";
var session = configuration.CreateSession();
var user = await session
    .Sql(sql)
    .Parameter("@EmailAddress", email)
    .QuerySingleAsync<User>();
SQL Server Features
PM> Install-Package FluentCommand.SqlServer
Bulk Copy
Using SQL Server bulk copy feature to import a lot of data.
using (var session = configuration.CreateSession())
{
    session.BulkCopy("[User]")
        .AutoMap()
        .Ignore("RowVersion")
        .WriteToServer(users);
}
Merge Data
Generate and merge data into a table
var users = generator.List<UserImport>(100);
int rows;
using (var session = configuration.CreateSession())
{
    rows = session
        .MergeData("dbo.User")
        .Map<UserImport>(m => m
            .AutoMap()
            .Column(p => p.EmailAddress).Key()
        )
        .Execute(users);
}
| Product | Versions 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 is compatible. 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 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. | 
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. | 
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. | 
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. | 
| MonoAndroid | monoandroid was computed. | 
| MonoMac | monomac was computed. | 
| MonoTouch | monotouch was computed. | 
| Tizen | tizen40 was computed. tizen60 was computed. | 
| Xamarin.iOS | xamarinios was computed. | 
| Xamarin.Mac | xamarinmac was computed. | 
| Xamarin.TVOS | xamarintvos was computed. | 
| Xamarin.WatchOS | xamarinwatchos was computed. | 
- 
                                                    .NETStandard 2.0- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.10)
- PolySharp (>= 1.15.0)
- System.ComponentModel.Annotations (>= 5.0.0)
 
- 
                                                    net8.0- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.10)
- PolySharp (>= 1.15.0)
 
- 
                                                    net9.0- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.10)
- PolySharp (>= 1.15.0)
 
NuGet packages (7)
Showing the top 5 NuGet packages that depend on FluentCommand:
| Package | Downloads | 
|---|---|
| FluentCommand.SqlServer Fluent Wrapper for DbCommand | |
| FluentCommand.EntityFactory Fluent Wrapper for DbCommand | |
| FluentCommand.Batch Fluent Wrapper for DbCommand | |
| FluentCommand.Json Fluent Wrapper for DbCommand | |
| FluentCommand.Dapper Fluent Wrapper for DbCommand | 
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | 
|---|---|---|
| 13.4.1 | 584 | 10/15/2025 | 
| 13.4.0 | 956 | 9/8/2025 | 
| 13.3.3 | 1,166 | 7/16/2025 | 
| 13.3.1 | 268 | 7/15/2025 | 
| 13.3.0 | 274 | 7/13/2025 | 
| 13.2.1 | 388 | 6/17/2025 | 
| 13.2.0 | 454 | 6/14/2025 | 
| 13.1.0 | 4,933 | 2/16/2025 | 
| 13.0.0 | 1,549 | 11/13/2024 | 
| 12.13.2 | 594 | 9/21/2024 | 
| 12.13.1 | 376 | 9/19/2024 | 
| 12.13.0 | 419 | 9/16/2024 | 
| 12.12.0 | 501 | 9/7/2024 | 
| 12.11.0 | 941 | 8/9/2024 | 
| 12.10.8 | 425 | 8/8/2024 | 
| 12.10.7 | 579 | 7/17/2024 | 
| 12.10.6 | 513 | 7/9/2024 | 
| 12.10.5 | 377 | 7/9/2024 | 
| 12.10.4 | 397 | 6/7/2024 | 
| 12.10.3 | 478 | 5/14/2024 | 
| 12.10.2 | 743 | 5/10/2024 | 
| 12.10.1 | 410 | 5/6/2024 | 
| 12.10.0 | 402 | 5/6/2024 | 
| 12.9.1 | 386 | 5/3/2024 | 
| 12.9.0 | 430 | 4/26/2024 | 
| 12.8.0 | 437 | 4/17/2024 | 
| 12.7.0 | 532 | 3/19/2024 | 
| 12.6.0 | 439 | 2/4/2024 | 
| 12.5.0 | 1,431 | 11/24/2023 | 
| 12.4.2 | 388 | 10/28/2023 | 
| 12.4.1 | 407 | 10/12/2023 | 
| 12.4.0 | 397 | 10/12/2023 | 
| 12.3.0 | 8,460 | 9/14/2023 | 
| 12.2.0 | 389 | 9/14/2023 | 
| 12.1.0 | 368 | 9/13/2023 | 
| 12.0.0 | 360 | 9/12/2023 | 
| 12.0.0-beta.1 | 132 | 9/11/2023 | 
| 11.0.0 | 478 | 8/16/2023 | 
| 10.2.0 | 8,542 | 8/9/2023 | 
| 10.1.6 | 547 | 7/28/2023 | 
| 10.1.5 | 533 | 7/6/2023 | 
| 10.0.707 | 1,600 | 3/13/2023 | 
| 10.0.702 | 1,717 | 2/23/2023 | 
| 10.0.701 | 1,036 | 2/23/2023 | 
| 10.0.664 | 1,528 | 1/31/2023 | 
| 10.0.659 | 1,197 | 1/25/2023 | 
| 10.0.637 | 1,478 | 12/28/2022 | 
| 10.0.636 | 1,288 | 12/27/2022 | 
| 10.0.632 | 1,380 | 12/19/2022 | 
| 10.0.625 | 1,342 | 12/13/2022 | 
| 10.0.619 | 1,465 | 12/7/2022 | 
| 10.0.616 | 1,392 | 12/6/2022 | 
| 10.0.610 | 1,477 | 11/30/2022 | 
| 9.5.591 | 11,354 | 11/9/2022 | 
| 9.5.574 | 1,554 | 11/7/2022 | 
| 9.5.570 | 1,593 | 11/6/2022 | 
| 9.5.554 | 1,929 | 10/21/2022 | 
| 9.5.553 | 1,779 | 10/20/2022 | 
| 9.5.552 | 1,867 | 10/19/2022 | 
| 9.5.551 | 1,788 | 10/19/2022 | 
| 9.5.550 | 1,792 | 10/18/2022 | 
| 9.5.549 | 1,718 | 10/18/2022 | 
| 9.5.548 | 1,795 | 10/18/2022 | 
| 9.5.547 | 1,739 | 10/17/2022 | 
| 9.5.546 | 1,806 | 10/17/2022 | 
| 9.5.545 | 1,857 | 10/16/2022 | 
| 9.5.544 | 1,807 | 10/15/2022 | 
| 9.5.540 | 1,851 | 10/15/2022 | 
| 9.0.538 | 1,949 | 10/11/2022 | 
| 9.0.537 | 1,818 | 10/10/2022 | 
| 9.0.534 | 1,850 | 10/9/2022 | 
| 9.0.533 | 1,806 | 10/7/2022 | 
| 9.0.532 | 1,894 | 10/3/2022 | 
| 9.0.530 | 1,907 | 10/2/2022 | 
| 9.0.527 | 1,871 | 10/1/2022 | 
| 9.0.526 | 1,862 | 10/1/2022 | 
| 9.0.525 | 1,882 | 10/1/2022 | 
| 9.0.524 | 1,836 | 9/30/2022 | 
| 9.0.523 | 1,837 | 9/30/2022 | 
| 9.0.522 | 1,909 | 9/30/2022 | 
| 9.0.520 | 1,840 | 9/29/2022 | 
| 9.0.519 | 1,908 | 9/29/2022 | 
| 9.0.518 | 1,848 | 9/29/2022 | 
| 9.0.514 | 1,656 | 9/29/2022 | 
| 8.0.468 | 1,879 | 4/23/2022 | 
| 8.0.430 | 1,105 | 12/22/2021 | 
| 8.0.416 | 1,097 | 11/18/2021 | 
| 7.0.0.393 | 1,202 | 10/21/2021 | 
| 7.0.0.359 | 1,424 | 4/6/2021 | 
| 7.0.0.335 | 1,269 | 2/15/2021 | 
| 7.0.0.296 | 1,424 | 11/16/2020 | 
| 7.0.0.293 | 1,459 | 11/12/2020 | 
| 6.0.0.249 | 1,568 | 9/16/2020 | 
| 6.0.0.240 | 1,448 | 9/5/2020 | 
| 5.0.0.231 | 1,543 | 8/17/2020 | 
| 5.0.0.230 | 1,339 | 8/12/2020 | 
| 5.0.0.220 | 1,298 | 8/10/2020 | 
| 4.1.0.202 | 1,302 | 6/25/2020 | 
| 4.1.0.201 | 1,289 | 6/25/2020 | 
| 4.1.0.186 | 1,341 | 6/15/2020 | 
| 4.1.0.177 | 1,331 | 6/5/2020 | 
| 4.1.0.176 | 1,282 | 6/5/2020 | 
| 4.1.0.167 | 1,301 | 5/29/2020 | 
| 4.1.0.166 | 1,324 | 5/27/2020 | 
| 4.1.0.165 | 1,325 | 5/25/2020 | 
| 4.0.0.148 | 1,389 | 4/11/2020 | 
| 4.0.0.108 | 1,522 | 12/5/2019 | 
| 4.0.0.85 | 1,320 | 11/30/2019 | 
| 4.0.0.83 | 1,340 | 11/29/2019 | 
| 3.0.0.49 | 1,465 | 5/20/2019 | 
| 2.0.0.46 | 1,401 | 12/13/2018 | 
| 1.0.0.8 | 2,533 | 10/28/2014 |