diff --git a/src/Codehard.Functional/CodeHard.Function.FSharp.Tests.Types/CodeHard.Functional.FSharp.Tests.Types.fsproj b/src/Codehard.Functional/CodeHard.Function.FSharp.Tests.Types/CodeHard.Functional.FSharp.Tests.Types.fsproj
index 0bc9a20..17a7ad5 100644
--- a/src/Codehard.Functional/CodeHard.Function.FSharp.Tests.Types/CodeHard.Functional.FSharp.Tests.Types.fsproj
+++ b/src/Codehard.Functional/CodeHard.Function.FSharp.Tests.Types/CodeHard.Functional.FSharp.Tests.Types.fsproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.AspNetCore/ControllerExtensions.cs b/src/Codehard.Functional/Codehard.Functional.AspNetCore/ControllerExtensions.cs
index 7e3392a..214bde3 100644
--- a/src/Codehard.Functional/Codehard.Functional.AspNetCore/ControllerExtensions.cs
+++ b/src/Codehard.Functional/Codehard.Functional.AspNetCore/ControllerExtensions.cs
@@ -111,9 +111,10 @@ public static IActionResult RunToResult(
public static async Task RunToResultAsync(
this Eff eff,
HttpStatusCode successStatusCode = HttpStatusCode.OK,
- ILogger? logger = default)
+ ILogger? logger = default,
+ CancellationToken cancellationToken = default)
{
- var fin = await eff.RunAsync();
+ var fin = await eff.RunAsync(EnvIO.New(token: cancellationToken));
return
fin.MatchToResult(
diff --git a/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/Codehard.Functional.EntityFramework.Tests.csproj b/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/Codehard.Functional.EntityFramework.Tests.csproj
index 4a14b63..a56fc53 100644
--- a/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/Codehard.Functional.EntityFramework.Tests.csproj
+++ b/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/Codehard.Functional.EntityFramework.Tests.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/QueryableExtensionsTests.cs b/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/QueryableExtensionsTests.cs
index ddaf2bd..7e10bab 100644
--- a/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/QueryableExtensionsTests.cs
+++ b/src/Codehard.Functional/Codehard.Functional.EntityFramework.Tests/QueryableExtensionsTests.cs
@@ -5,6 +5,7 @@
using Codehard.Functional.EntityFramework.Tests.Entities;
using Codehard.Infrastructure.EntityFramework.Extensions;
+using static Codehard.Functional.EntityFramework.Extensions.QueryablePrelude;
namespace Codehard.Functional.EntityFramework.Tests;
@@ -18,7 +19,7 @@ private static SqliteConnection CreateInMemoryDatabase()
}
[Fact]
- public async Task ToListEffRt_ShouldReturnList()
+ public async Task ToListEff_ShouldReturnList()
{
// Arrange
var assembly = Assembly.GetExecutingAssembly();
@@ -29,6 +30,7 @@ public async Task ToListEffRt_ShouldReturnList()
await using var context = new TestDbContext(
options,
builder => builder.ApplyConfigurationsFromAssemblyFor(assembly));
+
await context.Database.EnsureCreatedAsync();
var entityId = Guid.NewGuid();
@@ -56,4 +58,44 @@ public async Task ToListEffRt_ShouldReturnList()
Assert.NotNull(resultEntity);
Assert.Single(resultEntity);
}
+
+ [Fact]
+ public async Task FilterRtAndToListEff_ShouldReturnList()
+ {
+ // Arrange
+ var assembly = Assembly.GetExecutingAssembly();
+ var options = new DbContextOptionsBuilder()
+ .UseSqlite(CreateInMemoryDatabase())
+ .Options;
+
+ await using var context = new TestDbContext(
+ options,
+ builder => builder.ApplyConfigurationsFromAssemblyFor(assembly));
+
+ await context.Database.EnsureCreatedAsync();
+
+ var entityId = Guid.NewGuid();
+ var entity = new EntityA
+ {
+ Id = entityId,
+ };
+
+ context.As.Add(entity);
+ await context.SaveChangesAsync();
+
+ // Act
+ var workflow =
+ from @as in From()
+ from list in
+ @as.Where(a => a.Id == entityId)
+ .ToListEff()
+ select list;
+
+ // Assert
+ var listResult = await workflow.RunAsync(context);
+ var resultEntity = listResult.ThrowIfFail();
+
+ Assert.NotNull(resultEntity);
+ Assert.Single(resultEntity);
+ }
}
diff --git a/src/Codehard.Functional/Codehard.Functional.EntityFramework/Codehard.Functional.EntityFramework.csproj b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Codehard.Functional.EntityFramework.csproj
index e7b5870..e8a1031 100644
--- a/src/Codehard.Functional/Codehard.Functional.EntityFramework/Codehard.Functional.EntityFramework.csproj
+++ b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Codehard.Functional.EntityFramework.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryableExtensions.cs b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryableExtensions.cs
index bbc100c..eaa7254 100644
--- a/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryableExtensions.cs
+++ b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryableExtensions.cs
@@ -1,6 +1,5 @@
using System.Linq.Expressions;
using LanguageExt;
-
using static LanguageExt.Prelude;
// ReSharper disable once CheckNamespace
diff --git a/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryablePrelude.cs b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryablePrelude.cs
new file mode 100644
index 0000000..faa9577
--- /dev/null
+++ b/src/Codehard.Functional/Codehard.Functional.EntityFramework/Extensions/QueryablePrelude.cs
@@ -0,0 +1,63 @@
+using System.Linq.Expressions;
+using LanguageExt;
+using Microsoft.EntityFrameworkCore;
+
+using Codehard.Common.DomainModel;
+
+using static LanguageExt.Prelude;
+
+namespace Codehard.Functional.EntityFramework.Extensions;
+
+public static class QueryablePrelude
+{
+ ///
+ /// Asynchronously converts a sequence to a list within an Eff monad.
+ ///
+ /// The type of the elements of the source sequence.
+ ///
+ /// An Eff monad that represents the asynchronous operation. The Eff monad wraps a that contains elements from the input sequence.
+ ///
+ public static Eff, List> ToListEff()
+ {
+ return
+ LanguageExt.Eff, List>.LiftIO(
+ static source =>
+ liftIO(env => source.ToListAsync(env.Token)));
+ }
+
+ ///
+ /// Asynchronously converts a sequence to an array within an Eff monad.
+ ///
+ /// The type of the elements of the source sequence.
+ ///
+ /// An Eff monad that represents the asynchronous operation. The Eff monad wraps an array that contains elements from the input sequence.
+ ///
+ public static Eff, T[]> ToArrayEff()
+ {
+ return
+ LanguageExt.Eff, T[]>.LiftIO(
+ static source =>
+ liftIO(env => source.ToArrayAsync(env.Token)));
+ }
+
+ public static Eff> From()
+ where T : class
+ {
+ return
+ LanguageExt.Eff>.Lift(
+ dbContext => dbContext.Set().AsQueryable());
+ }
+
+ public static Eff, Option> FindByKey(
+ TKey key)
+ where TEntity : class, IEntity
+ where TKey : struct
+ {
+ return
+ LanguageExt.Eff, Option>.LiftIO(
+ source =>
+ liftIO(async env => Optional(await source.FindAsync(
+ new object[] { key },
+ cancellationToken: env.Token))));
+ }
+}
\ No newline at end of file
diff --git a/src/Codehard.Functional/Codehard.Functional.FSharp/Codehard.Functional.FSharp.csproj b/src/Codehard.Functional/Codehard.Functional.FSharp/Codehard.Functional.FSharp.csproj
index b98e4a2..809a987 100644
--- a/src/Codehard.Functional/Codehard.Functional.FSharp/Codehard.Functional.FSharp.csproj
+++ b/src/Codehard.Functional/Codehard.Functional.FSharp/Codehard.Functional.FSharp.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.Marten/Codehard.Functional.Marten.csproj b/src/Codehard.Functional/Codehard.Functional.Marten/Codehard.Functional.Marten.csproj
index 5b37860..bf62988 100644
--- a/src/Codehard.Functional/Codehard.Functional.Marten/Codehard.Functional.Marten.csproj
+++ b/src/Codehard.Functional/Codehard.Functional.Marten/Codehard.Functional.Marten.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.MediatR/Codehard.Functional.MediatR.csproj b/src/Codehard.Functional/Codehard.Functional.MediatR/Codehard.Functional.MediatR.csproj
index 406fadb..a7677b7 100644
--- a/src/Codehard.Functional/Codehard.Functional.MediatR/Codehard.Functional.MediatR.csproj
+++ b/src/Codehard.Functional/Codehard.Functional.MediatR/Codehard.Functional.MediatR.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Codehard.Functional/Codehard.Functional.Tests/AffGuardExtTests.cs b/src/Codehard.Functional/Codehard.Functional.Tests/AffGuardExtTests.cs
deleted file mode 100644
index b12ad4e..0000000
--- a/src/Codehard.Functional/Codehard.Functional.Tests/AffGuardExtTests.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using static Codehard.Functional.Prelude;
-
-namespace Codehard.Functional.Tests;
-
-public class AffGuardExtTests
-{
- [Fact]
- public async Task WhenGuardNoneOnSomeValue_ShouldStayOnSuccCase()
- {
- // Act
- var eff =
- EffOption(() => ValueTask.FromResult((int?)1))
- .GuardNotNone("There is something wrong");
-
- var fin = await eff.RunAsync();
-
- // Assert
- var a = fin.ThrowIfFail();
-
- Assert.Equal(1, a);
- }
-
- [Fact]
- public async Task WhenGuardNoneOnNullValue_ShouldGoToFailCase()
- {
- // Act
- var eff =
- EffOption(() => ValueTask.FromResult((int?)null))
- .GuardNotNone("There is no value");
-
- var fin = await eff.RunAsync();
-
- // Assert
- Assert.False(fin.IsSucc);
- }
-}
\ No newline at end of file
diff --git a/src/Codehard.Functional/Codehard.Functional.Tests/EffGuardExtTests.cs b/src/Codehard.Functional/Codehard.Functional.Tests/EffGuardExtTests.cs
index eef3d1c..065354a 100644
--- a/src/Codehard.Functional/Codehard.Functional.Tests/EffGuardExtTests.cs
+++ b/src/Codehard.Functional/Codehard.Functional.Tests/EffGuardExtTests.cs
@@ -33,4 +33,34 @@ public void WhenGuardNoneOnNullValue_ShouldGoToFailCase()
// Assert
Assert.False(fin.IsSucc);
}
+
+ [Fact]
+ public async Task WhenGuardNoneOnSomeValueAsync_ShouldStayOnSuccCase()
+ {
+ // Act
+ var eff =
+ EffOption(() => ValueTask.FromResult((int?)1))
+ .GuardNotNone("There is something wrong");
+
+ var fin = await eff.RunAsync();
+
+ // Assert
+ var a = fin.ThrowIfFail();
+
+ Assert.Equal(1, a);
+ }
+
+ [Fact]
+ public async Task WhenGuardNoneOnNullValueAsync_ShouldGoToFailCase()
+ {
+ // Act
+ var eff =
+ EffOption(() => ValueTask.FromResult((int?)null))
+ .GuardNotNone("There is no value");
+
+ var fin = await eff.RunAsync();
+
+ // Assert
+ Assert.False(fin.IsSucc);
+ }
}
\ No newline at end of file
diff --git a/src/Codehard.Functional/Codehard.Functional/Codehard.Functional.csproj b/src/Codehard.Functional/Codehard.Functional/Codehard.Functional.csproj
index 510bfc4..30a7c22 100644
--- a/src/Codehard.Functional/Codehard.Functional/Codehard.Functional.csproj
+++ b/src/Codehard.Functional/Codehard.Functional/Codehard.Functional.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Codehard.Infrastructure/Codehard.Infrastructure.EntityFramework.Tests/ModelBuilderExtensionsTests.cs b/src/Codehard.Infrastructure/Codehard.Infrastructure.EntityFramework.Tests/ModelBuilderExtensionsTests.cs
index 99bb9e4..e02b9f0 100644
--- a/src/Codehard.Infrastructure/Codehard.Infrastructure.EntityFramework.Tests/ModelBuilderExtensionsTests.cs
+++ b/src/Codehard.Infrastructure/Codehard.Infrastructure.EntityFramework.Tests/ModelBuilderExtensionsTests.cs
@@ -35,6 +35,8 @@ public void WhenUseApplyConfigurationsFromAssemblyForSpecificContext_ShouldApply
// +2 because of the Money type and the Nullable Money type
Assert.Equal(expectedEntityTypes + 3, actualEntityTypes);
+
+ return;
static SqliteConnection CreateInMemoryDatabase()
{