diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index b82f24f..0b0dcab 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -36,7 +36,7 @@ jobs:
- run: dotnet restore
- run: dotnet build --no-restore -c Release -p:Version=${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}
- run: dotnet pack --no-build --no-restore --nologo --output=dist -c Release
- - run: gh release create "v${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}" --notes-file CHANGELOG.md "dist/FruityFoundation.Base.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.Db.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.FsBase.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.DataAccess.Abstractions.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.DataAccess.Core.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg"
+ - run: gh release create "v${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}" --notes-file CHANGELOG.md "dist/FruityFoundation.Base.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.Db.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.FsBase.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.DataAccess.Abstractions.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.DataAccess.Core.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" "dist/FruityFoundation.DataAccess.Sqlite.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg"
env:
GH_TOKEN: ${{ github.token }}
- name: Publish to NuGet
@@ -48,3 +48,4 @@ jobs:
dotnet nuget push "FruityFoundation.DataAccess.Abstractions.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" --api-key=${{ secrets.NUGET_API_KEY }} --source=https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push "FruityFoundation.DataAccess.Abstractions.FSharp.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" --api-key=${{ secrets.NUGET_API_KEY }} --source=https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push "FruityFoundation.DataAccess.Core.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" --api-key=${{ secrets.NUGET_API_KEY }} --source=https://api.nuget.org/v3/index.json --skip-duplicate
+ dotnet nuget push "FruityFoundation.DataAccess.Sqlite.${{ steps.generate-version.outputs.RELEASE_VERSION_NUMBER }}.nupkg" --api-key=${{ secrets.NUGET_API_KEY }} --source=https://api.nuget.org/v3/index.json --skip-duplicate
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..32969e5
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+ true
+
+
diff --git a/FruityFoundation.DataAccess.Core/DbConnectionFactory.cs b/FruityFoundation.DataAccess.Core/DbConnectionFactory.cs
deleted file mode 100644
index 7a9c3fc..0000000
--- a/FruityFoundation.DataAccess.Core/DbConnectionFactory.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Data.Common;
-using FruityFoundation.DataAccess.Abstractions;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace FruityFoundation.DataAccess.Core;
-
-public class DbConnectionFactory : IDbConnectionFactory
-{
- private readonly IServiceProvider _serviceProvider;
-
- public DbConnectionFactory(IServiceProvider serviceProvider)
- {
- _serviceProvider = serviceProvider;
- }
-
- public INonTransactionalDbConnection CreateConnection()
- {
- var nonTxConnection = _serviceProvider.GetRequiredService>();
- return nonTxConnection;
- }
-
- public INonTransactionalDbConnection CreateReadOnlyConnection()
- {
- var nonTxConnection = _serviceProvider.GetRequiredService>();
- return nonTxConnection;
- }
-}
diff --git a/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj b/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
index 30a0b16..8902fb2 100644
--- a/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
+++ b/FruityFoundation.DataAccess.Core/FruityFoundation.DataAccess.Core.csproj
@@ -22,7 +22,6 @@
-
diff --git a/FruityFoundation.DataAccess.Core/ServiceCollectionExtensions.cs b/FruityFoundation.DataAccess.Core/ServiceCollectionExtensions.cs
deleted file mode 100644
index dfa19c1..0000000
--- a/FruityFoundation.DataAccess.Core/ServiceCollectionExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using FruityFoundation.DataAccess.Abstractions;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace FruityFoundation.DataAccess.Core;
-
-[ExcludeFromCodeCoverage(Justification = "Dependency injection helpers")]
-public static class ServiceCollectionExtensions
-{
- public static void AddDataAccessCore(
- this IServiceCollection services,
- Func> readWriteConnectionImplementationFactory,
- Func> readOnlyConnectionImplementationFactory
- )
- {
- services.AddTransient>(readWriteConnectionImplementationFactory);
- services.AddTransient>(readOnlyConnectionImplementationFactory);
- services.AddSingleton();
- }
-}
diff --git a/FruityFoundation.DataAccess.Sqlite/FruityFoundation.DataAccess.Sqlite.csproj b/FruityFoundation.DataAccess.Sqlite/FruityFoundation.DataAccess.Sqlite.csproj
new file mode 100644
index 0000000..4c61bb6
--- /dev/null
+++ b/FruityFoundation.DataAccess.Sqlite/FruityFoundation.DataAccess.Sqlite.csproj
@@ -0,0 +1,29 @@
+
+
+
+ enable
+ enable
+ true
+ Kyle Ratti
+ https://github.com/kyleratti/FruityFoundation
+ 1.12.2
+ true
+ LICENSE
+ net8.0;net6.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FruityFoundation.DataAccess.Sqlite/ServiceCollectionExtensions.cs b/FruityFoundation.DataAccess.Sqlite/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..8bc3ca3
--- /dev/null
+++ b/FruityFoundation.DataAccess.Sqlite/ServiceCollectionExtensions.cs
@@ -0,0 +1,36 @@
+using System.Diagnostics.CodeAnalysis;
+using FruityFoundation.DataAccess.Abstractions;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace FruityFoundation.DataAccess.Sqlite;
+
+[ExcludeFromCodeCoverage(Justification = "Dependency injection helpers")]
+public static class ServiceCollectionExtensions
+{
+ public static void AddSqliteDataAccess(
+ this IServiceCollection services,
+ Func getReadWriteConnectionString,
+ Func getReadOnlyConnectionString
+ )
+ {
+ services.AddScoped>(serviceProvider =>
+ {
+ var connectionFactory = serviceProvider.GetRequiredService();
+
+ return connectionFactory.CreateConnection();
+ });
+
+ services.AddScoped>(serviceProvider =>
+ {
+ var connectionFactory = serviceProvider.GetRequiredService();
+
+ return connectionFactory.CreateReadOnlyConnection();
+ });
+
+ services.AddSingleton(serviceProvider =>
+ new SqliteDbConnectionFactory(
+ serviceProvider,
+ getReadOnlyConnectionString: getReadOnlyConnectionString,
+ getReadWriteConnectionString: getReadWriteConnectionString));
+ }
+}
diff --git a/FruityFoundation.DataAccess.Sqlite/SqliteDbConnectionFactory.cs b/FruityFoundation.DataAccess.Sqlite/SqliteDbConnectionFactory.cs
new file mode 100644
index 0000000..9cb7150
--- /dev/null
+++ b/FruityFoundation.DataAccess.Sqlite/SqliteDbConnectionFactory.cs
@@ -0,0 +1,40 @@
+using FruityFoundation.DataAccess.Abstractions;
+using FruityFoundation.DataAccess.Core;
+using Microsoft.Data.Sqlite;
+
+namespace FruityFoundation.DataAccess.Sqlite;
+
+public class SqliteDbConnectionFactory : IDbConnectionFactory
+{
+ private readonly IServiceProvider _serviceProvider;
+ private readonly Func _getReadWriteConnectionString;
+ private readonly Func _getReadOnlyConnectionString;
+
+ public SqliteDbConnectionFactory(
+ IServiceProvider serviceProvider,
+ Func getReadWriteConnectionString,
+ Func getReadOnlyConnectionString)
+ {
+ _serviceProvider = serviceProvider;
+ _getReadWriteConnectionString = getReadWriteConnectionString;
+ _getReadOnlyConnectionString = getReadOnlyConnectionString;
+ }
+
+ ///
+ public INonTransactionalDbConnection CreateConnection()
+ {
+ var connectionString = _getReadWriteConnectionString(_serviceProvider);
+ var connection = new SqliteConnection(connectionString);
+
+ return new NonTransactionalDbConnection(connection);
+ }
+
+ ///
+ public INonTransactionalDbConnection CreateReadOnlyConnection()
+ {
+ var connectionString = _getReadOnlyConnectionString(_serviceProvider);
+ var connection = new SqliteConnection(connectionString);
+
+ return new NonTransactionalDbConnection(connection);
+ }
+}
diff --git a/FruityFoundation.Tests.DataAccess.Abstractions.FSharp/FruityFoundation.Tests.DataAccess.Abstractions.FSharp.fsproj b/FruityFoundation.Tests.DataAccess.Abstractions.FSharp/FruityFoundation.Tests.DataAccess.Abstractions.FSharp.fsproj
index 7c3288d..7a91cfc 100644
--- a/FruityFoundation.Tests.DataAccess.Abstractions.FSharp/FruityFoundation.Tests.DataAccess.Abstractions.FSharp.fsproj
+++ b/FruityFoundation.Tests.DataAccess.Abstractions.FSharp/FruityFoundation.Tests.DataAccess.Abstractions.FSharp.fsproj
@@ -26,6 +26,7 @@
+
diff --git a/FruityFoundation.Tests.DataAccess.Sqlite/FruityFoundation.Tests.DataAccess.Sqlite.csproj b/FruityFoundation.Tests.DataAccess.Sqlite/FruityFoundation.Tests.DataAccess.Sqlite.csproj
new file mode 100644
index 0000000..4054c9f
--- /dev/null
+++ b/FruityFoundation.Tests.DataAccess.Sqlite/FruityFoundation.Tests.DataAccess.Sqlite.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FruityFoundation.Tests.DataAccess.Sqlite/SqliteDbConnectionFactoryTests.cs b/FruityFoundation.Tests.DataAccess.Sqlite/SqliteDbConnectionFactoryTests.cs
new file mode 100644
index 0000000..ead2e49
--- /dev/null
+++ b/FruityFoundation.Tests.DataAccess.Sqlite/SqliteDbConnectionFactoryTests.cs
@@ -0,0 +1,39 @@
+using FruityFoundation.DataAccess.Abstractions;
+using FruityFoundation.DataAccess.Sqlite;
+
+namespace FruityFoundation.Tests.DataAccess.Sqlite;
+
+public class SqliteDbConnectionFactoryTests
+{
+ [Test]
+ public void CreateConnection_WithValidConnectionString_ReturnsNonTransactionalDbConnection_ReadWrite()
+ {
+ // Arrange
+ var connectionFactory = new SqliteDbConnectionFactory(
+ serviceProvider: null!,
+ getReadWriteConnectionString: _ => "Data Source=:memory:",
+ getReadOnlyConnectionString: null!);
+
+ // Act
+ var result = connectionFactory.CreateConnection();
+
+ // Assert
+ Assert.That(result, Is.InstanceOf>());
+ }
+
+ [Test]
+ public void CreateReadOnlyConnection_WithValidConnectionString_ReturnsNonTransactionalDbConnection_ReadOnly()
+ {
+ // Arrange
+ var connectionFactory = new SqliteDbConnectionFactory(
+ serviceProvider: null!,
+ getReadWriteConnectionString: null!,
+ getReadOnlyConnectionString: _ => "Data Source=:memory:");
+
+ // Act
+ var result = connectionFactory.CreateReadOnlyConnection();
+
+ // Assert
+ Assert.That(result, Is.InstanceOf>());
+ }
+}
diff --git a/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj b/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj
index 1e2d1e4..d5fc0b6 100644
--- a/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj
+++ b/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj
@@ -30,6 +30,7 @@
+
diff --git a/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj b/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj
index fe56c82..f77053d 100644
--- a/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj
+++ b/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj
@@ -28,6 +28,7 @@
+
diff --git a/FruityFoundation.sln b/FruityFoundation.sln
index 3130355..ac16973 100644
--- a/FruityFoundation.sln
+++ b/FruityFoundation.sln
@@ -24,6 +24,10 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FruityFoundation.DataAccess
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FruityFoundation.Tests.DataAccess.Abstractions.FSharp", "FruityFoundation.Tests.DataAccess.Abstractions.FSharp\FruityFoundation.Tests.DataAccess.Abstractions.FSharp.fsproj", "{27F4FB64-7A51-4315-BDAA-6EE07736C976}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FruityFoundation.DataAccess.Sqlite", "FruityFoundation.DataAccess.Sqlite\FruityFoundation.DataAccess.Sqlite.csproj", "{2DB2E605-68E8-47E3-A183-985C1A52B56A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FruityFoundation.Tests.DataAccess.Sqlite", "FruityFoundation.Tests.DataAccess.Sqlite\FruityFoundation.Tests.DataAccess.Sqlite.csproj", "{A1AB7658-7310-490A-82BE-DAABCC204EA4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -70,6 +74,14 @@ Global
{27F4FB64-7A51-4315-BDAA-6EE07736C976}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27F4FB64-7A51-4315-BDAA-6EE07736C976}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27F4FB64-7A51-4315-BDAA-6EE07736C976}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2DB2E605-68E8-47E3-A183-985C1A52B56A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2DB2E605-68E8-47E3-A183-985C1A52B56A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2DB2E605-68E8-47E3-A183-985C1A52B56A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2DB2E605-68E8-47E3-A183-985C1A52B56A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A1AB7658-7310-490A-82BE-DAABCC204EA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A1AB7658-7310-490A-82BE-DAABCC204EA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A1AB7658-7310-490A-82BE-DAABCC204EA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A1AB7658-7310-490A-82BE-DAABCC204EA4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{50A75644-A1C3-4495-9DEB-DBB12D9334B5} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF}
@@ -79,5 +91,7 @@ Global
{B65527CC-218A-4EA3-93DC-985713B5DFF4} = {5C3A014A-7931-4A36-95F0-5EFE15AB06A3}
{B2E0156B-B631-4C80-A129-59472D2D0A77} = {5C3A014A-7931-4A36-95F0-5EFE15AB06A3}
{27F4FB64-7A51-4315-BDAA-6EE07736C976} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF}
+ {2DB2E605-68E8-47E3-A183-985C1A52B56A} = {5C3A014A-7931-4A36-95F0-5EFE15AB06A3}
+ {A1AB7658-7310-490A-82BE-DAABCC204EA4} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF}
EndGlobalSection
EndGlobal