diff --git a/FruityFoundation.DataAccess.Abstractions.FSharp/FruityFoundation.DataAccess.Abstractions.FSharp.fsproj b/FruityFoundation.DataAccess.Abstractions.FSharp/FruityFoundation.DataAccess.Abstractions.FSharp.fsproj
index a657707..2bde81f 100644
--- a/FruityFoundation.DataAccess.Abstractions.FSharp/FruityFoundation.DataAccess.Abstractions.FSharp.fsproj
+++ b/FruityFoundation.DataAccess.Abstractions.FSharp/FruityFoundation.DataAccess.Abstractions.FSharp.fsproj
@@ -21,7 +21,9 @@
+
+
diff --git a/FruityFoundation.DataAccess.Abstractions.FSharp/ReadOnlyDb.fs b/FruityFoundation.DataAccess.Abstractions.FSharp/ReadOnlyDb.fs
index 34f3560..f7a91c9 100644
--- a/FruityFoundation.DataAccess.Abstractions.FSharp/ReadOnlyDb.fs
+++ b/FruityFoundation.DataAccess.Abstractions.FSharp/ReadOnlyDb.fs
@@ -5,6 +5,7 @@ open System.Collections.Generic
open System.Threading
open FSharp.Control
open FruityFoundation.DataAccess.Abstractions
+open FruityFoundation.FsBase
let private toKeyValuePair (parms : (string * obj) seq) =
parms
@@ -22,6 +23,11 @@ let querySingle<'a> (connection : IDatabaseConnection) (cancellationTo
return! connection.QuerySingle<'a>(sql, parms |> toKeyValuePair, cancellationToken)
}
+let tryQueryFirst<'a> (connection : ReadOnly IDatabaseConnection) (cancellationToken : CancellationToken) (sql : string) (parms : (string * obj) seq) = task {
+ let! result = connection.TryQueryFirst(sql, parms |> toKeyValuePair, cancellationToken)
+ return result |> Option.fromMaybe
+}
+
let execute (connection : IDatabaseConnection) (cancellationToken : CancellationToken) (sql : string) (parms : (string * obj) seq) = task {
return! connection.Execute(sql, parms |> toKeyValuePair, cancellationToken)
}
diff --git a/FruityFoundation.DataAccess.Abstractions.FSharp/ReadWriteDb.fs b/FruityFoundation.DataAccess.Abstractions.FSharp/ReadWriteDb.fs
index b6309e4..7aa168f 100644
--- a/FruityFoundation.DataAccess.Abstractions.FSharp/ReadWriteDb.fs
+++ b/FruityFoundation.DataAccess.Abstractions.FSharp/ReadWriteDb.fs
@@ -5,6 +5,7 @@ open System.Collections.Generic
open System.Threading
open FSharp.Control
open FruityFoundation.DataAccess.Abstractions
+open FruityFoundation.FsBase
let private toKeyValuePair (parms : (string * obj) seq) =
parms
@@ -22,6 +23,11 @@ let querySingle<'a> (connection : IDatabaseConnection) (cancellationT
return! connection.QuerySingle<'a>(sql, parms |> toKeyValuePair, cancellationToken)
}
+let tryQueryFirst<'a> (connection : ReadOnly IDatabaseConnection) (cancellationToken : CancellationToken) (sql : string) (parms : (string * obj) seq) = task {
+ let! result = connection.TryQueryFirst(sql, parms |> toKeyValuePair, cancellationToken)
+ return result |> Option.fromMaybe
+}
+
let execute (connection : IDatabaseConnection) (cancellationToken : CancellationToken) (sql : string) (parms : (string * obj) seq) = task {
return! connection.Execute(sql, parms |> toKeyValuePair, cancellationToken)
}
diff --git a/FruityFoundation.DataAccess.Abstractions/FruityFoundation.DataAccess.Abstractions.csproj b/FruityFoundation.DataAccess.Abstractions/FruityFoundation.DataAccess.Abstractions.csproj
index 8071f90..9cbb1ec 100644
--- a/FruityFoundation.DataAccess.Abstractions/FruityFoundation.DataAccess.Abstractions.csproj
+++ b/FruityFoundation.DataAccess.Abstractions/FruityFoundation.DataAccess.Abstractions.csproj
@@ -16,4 +16,8 @@
+
+
+
+
diff --git a/FruityFoundation.DataAccess.Abstractions/IDatabaseConnection.cs b/FruityFoundation.DataAccess.Abstractions/IDatabaseConnection.cs
index e60597a..f727174 100644
--- a/FruityFoundation.DataAccess.Abstractions/IDatabaseConnection.cs
+++ b/FruityFoundation.DataAccess.Abstractions/IDatabaseConnection.cs
@@ -1,4 +1,5 @@
using System.Data.Common;
+using FruityFoundation.Base.Structures;
namespace FruityFoundation.DataAccess.Abstractions;
@@ -8,6 +9,7 @@ public interface IDatabaseConnection where TConnectionType
public Task> Query(string sql, object? param = null, CancellationToken cancellationToken = default);
public IAsyncEnumerable QueryUnbuffered(string sql, object? param = null, CancellationToken cancellationToken = default);
public Task QuerySingle(string sql, object? param = null, CancellationToken cancellationToken = default);
+ public Task> TryQueryFirst(string sql, object? param = null, CancellationToken cancellationToken = default);
public Task Execute(string sql, object? param = null, CancellationToken cancellationToken = default);
public Task ExecuteScalar(string sql, object? param = null, CancellationToken cancellationToken = default);
public Task ExecuteReader(string sql, object? param = null, CancellationToken cancellationToken = default);
diff --git a/FruityFoundation.DataAccess.Abstractions/INonTransactionalDbConnection.cs b/FruityFoundation.DataAccess.Abstractions/INonTransactionalDbConnection.cs
index 2a8789c..f1fe980 100644
--- a/FruityFoundation.DataAccess.Abstractions/INonTransactionalDbConnection.cs
+++ b/FruityFoundation.DataAccess.Abstractions/INonTransactionalDbConnection.cs
@@ -1,4 +1,5 @@
using System.Data;
+using FruityFoundation.Base.Structures;
namespace FruityFoundation.DataAccess.Abstractions;
diff --git a/FruityFoundation.DataAccess.Core/DbTransaction.cs b/FruityFoundation.DataAccess.Core/DbTransaction.cs
index 1420da7..1908109 100644
--- a/FruityFoundation.DataAccess.Core/DbTransaction.cs
+++ b/FruityFoundation.DataAccess.Core/DbTransaction.cs
@@ -1,6 +1,7 @@
using System.Data.Common;
using System.Runtime.CompilerServices;
using Dapper;
+using FruityFoundation.Base.Structures;
using FruityFoundation.DataAccess.Abstractions;
namespace FruityFoundation.DataAccess.Core;
@@ -59,6 +60,16 @@ public class DbTransaction : IDatabaseTransactionConnection(command);
}
+ ///
+ public async Task> TryQueryFirst(string sql, object? param = null, CancellationToken cancellationToken = default)
+ {
+ if (_transaction.Connection is not { } conn)
+ throw new InvalidOperationException("Transaction connection cannot be null");
+
+ return await conn.QueryUnbufferedAsync(sql, param, transaction: _transaction)
+ .FirstOrEmptyAsync(cancellationToken);
+ }
+
///
public async Task Execute(string sql, object? param = null, CancellationToken cancellationToken = default)
{
diff --git a/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj b/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
index e67b563..0d0ac7b 100644
--- a/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
+++ b/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
@@ -17,6 +17,7 @@
+
diff --git a/FruityFoundation.DataAccess.Core/NonTransactionalDbConnection.cs b/FruityFoundation.DataAccess.Core/NonTransactionalDbConnection.cs
index 2c898e9..1e54d96 100644
--- a/FruityFoundation.DataAccess.Core/NonTransactionalDbConnection.cs
+++ b/FruityFoundation.DataAccess.Core/NonTransactionalDbConnection.cs
@@ -2,6 +2,7 @@
using System.Data.Common;
using System.Runtime.CompilerServices;
using Dapper;
+using FruityFoundation.Base.Structures;
using FruityFoundation.DataAccess.Abstractions;
namespace FruityFoundation.DataAccess.Core;
@@ -48,6 +49,15 @@ public class NonTransactionalDbConnection : INonTransactionalDb
CancellationToken cancellationToken = default
) => await _connection.QuerySingleAsync(new CommandDefinition(sql, param, cancellationToken: cancellationToken));
+ ///
+ public async Task> TryQueryFirst(
+ string sql,
+ object? param = null,
+ CancellationToken cancellationToken = default
+ ) =>
+ await _connection.QueryUnbufferedAsync(sql, param, transaction: null)
+ .FirstOrEmptyAsync(cancellationToken);
+
///
public async Task Execute(
string sql,