diff --git a/global.json b/global.json
index 20f482a..f15a959 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,6 @@
{
"sdk": {
- "version": "9.0.100"
+ "version": "9.0.100",
+ "rollForward": "latestMinor"
}
}
\ No newline at end of file
diff --git a/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomConventionSetPlugin.cs b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomConventionSetPlugin.cs
new file mode 100644
index 0000000..4bb5def
--- /dev/null
+++ b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomConventionSetPlugin.cs
@@ -0,0 +1,14 @@
+using Microsoft.EntityFrameworkCore.Metadata.Conventions;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
+
+namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
+
+public class CustomConventionSetPlugin : IConventionSetPlugin
+{
+ public ConventionSet ModifyConventions(ConventionSet conventionSet)
+ {
+ conventionSet.ModelFinalizingConventions.Add(new ProjectablesExpandQueryFiltersConvention());
+
+ return conventionSet;
+ }
+}
\ No newline at end of file
diff --git a/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablesExpandQueryFiltersConvention.cs b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablesExpandQueryFiltersConvention.cs
new file mode 100644
index 0000000..0b788e3
--- /dev/null
+++ b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablesExpandQueryFiltersConvention.cs
@@ -0,0 +1,26 @@
+using System.Linq.Expressions;
+using EntityFrameworkCore.Projectables.Extensions;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions;
+
+namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
+
+public class ProjectablesExpandQueryFiltersConvention : IModelFinalizingConvention
+{
+
+ ///
+ public void ProcessModelFinalizing(
+ IConventionModelBuilder modelBuilder,
+ IConventionContext context)
+ {
+ foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
+ {
+ var queryFilter = entityType.GetQueryFilter();
+ if (queryFilter != null)
+ {
+ // Expands query filters
+ entityType.SetQueryFilter(queryFilter.ExpandProjectables() as LambdaExpression);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectionOptionsExtension.cs b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectionOptionsExtension.cs
index ac593a9..fbfa4be 100644
--- a/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectionOptionsExtension.cs
+++ b/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectionOptionsExtension.cs
@@ -54,6 +54,9 @@ static object CreateTargetInstance(IServiceProvider services, ServiceDescriptor
return ActivatorUtilities.GetServiceOrCreateInstance(services, descriptor.ImplementationType!);
}
+ // Custom convention to handle global query filters, etc
+ services.AddScoped();
+
if (_compatibilityMode is CompatibilityMode.Full)
{
var targetDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(IQueryCompiler));
diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectQueryFilters.verified.txt b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectQueryFilters.verified.txt
new file mode 100644
index 0000000..1739868
--- /dev/null
+++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectQueryFilters.verified.txt
@@ -0,0 +1,15 @@
+SELECT [t0].[RecordDate]
+FROM [User] AS [u]
+INNER JOIN (
+ SELECT [t].[RecordDate], [t].[UserId]
+ FROM (
+ SELECT [o0].[RecordDate], [o0].[UserId], ROW_NUMBER() OVER(PARTITION BY [o0].[UserId] ORDER BY [o0].[RecordDate] DESC) AS [row]
+ FROM [Order] AS [o0]
+ ) AS [t]
+ WHERE [t].[row] <= 2
+) AS [t0] ON [u].[Id] = [t0].[UserId]
+WHERE (
+ SELECT TOP(1) [o].[Id]
+ FROM [Order] AS [o]
+ WHERE [u].[Id] = [o].[UserId]
+ ORDER BY [o].[RecordDate] DESC) > 100
\ No newline at end of file
diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.cs b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.cs
index 6ce61b3..a87da15 100644
--- a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.cs
+++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.cs
@@ -86,5 +86,17 @@ public Task ProjectOverMethodTakingDbContext()
return Verifier.Verify(query.ToQueryString());
}
+
+ [Fact]
+ public Task ProjectQueryFilters()
+ {
+ using var dbContext = new SampleUserWithGlobalQueryFilterDbContext();
+
+ var query = dbContext.Set()
+ .SelectMany(x => x.Last2Orders)
+ .Select(x => x.RecordDate);
+
+ return Verifier.Verify(query.ToQueryString());
+ }
}
}
diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/Helpers/SampleUserWithGlobalQueryFilterDbContext.cs b/tests/EntityFrameworkCore.Projectables.FunctionalTests/Helpers/SampleUserWithGlobalQueryFilterDbContext.cs
new file mode 100644
index 0000000..b8d284a
--- /dev/null
+++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/Helpers/SampleUserWithGlobalQueryFilterDbContext.cs
@@ -0,0 +1,21 @@
+using EntityFrameworkCore.Projectables.Infrastructure;
+using Microsoft.EntityFrameworkCore;
+
+namespace EntityFrameworkCore.Projectables.FunctionalTests.Helpers
+{
+ public class SampleUserWithGlobalQueryFilterDbContext : SampleDbContext
+ {
+ public SampleUserWithGlobalQueryFilterDbContext(CompatibilityMode compatibilityMode = CompatibilityMode.Full) : base(compatibilityMode)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.Entity(b => {
+ b.HasQueryFilter(u => u.LastOrder.Id > 100);
+ });
+ }
+ }
+}