Skip to content

Commit fbd2b8d

Browse files
authored
Merge pull request #124 from wassim-k/feature/ef9
Add .NET 9 + EF 9 support
2 parents f826bb5 + 7341626 commit fbd2b8d

File tree

67 files changed

+296
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+296
-22
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ jobs:
2929
- name: Setup .NET
3030
uses: actions/setup-dotnet@v1
3131
with:
32-
dotnet-version: 8.0.x
32+
dotnet-version: |
33+
8.0.x
34+
9.0.x
3335
- name: Restore dependencies
3436
run: dotnet restore
3537
- name: Build
@@ -46,7 +48,7 @@ jobs:
4648
- name: Setup .NET
4749
uses: actions/setup-dotnet@v1
4850
with:
49-
dotnet-version: 8.0.x
51+
dotnet-version: 9.0.x
5052
- name: Pack
5153
run: |
5254
dotnet pack -v normal -c Debug --include-symbols --include-source -p:PackageVersion=4.0.0-pre-$GITHUB_RUN_ID -o nupkg

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Setup .NET Core
2727
uses: actions/setup-dotnet@v1
2828
with:
29-
dotnet-version: 8.0.x
29+
dotnet-version: 9.0.x
3030
include-prerelease: True
3131
- name: Create Release NuGet package
3232
run: |

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<Nullable>enable</Nullable>
77
<EnableNETAnalyzers>true</EnableNETAnalyzers>
88
<NoWarn>CS1591</NoWarn>
9+
<NuGetAudit>false</NuGetAudit>
910
<ImplicitUsings>enable</ImplicitUsings>
1011
</PropertyGroup>
1112

Directory.Packages.props

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
44
</PropertyGroup>
5-
<ItemGroup>
6-
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.4.5" />
7-
<PackageVersion Include="BenchmarkDotNet" Version="0.13.2" />
8-
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
5+
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
96
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
107
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
118
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
12-
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
13-
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
14-
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
15-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
9+
</ItemGroup>
10+
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
11+
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
12+
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
13+
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
14+
</ItemGroup>
15+
<ItemGroup>
16+
<PackageVersion Include="Basic.Reference.Assemblies.Net80" Version="1.7.9" />
17+
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
18+
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
19+
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
20+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
21+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
22+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1623
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
1724
<PackageVersion Include="ScenarioTests.XUnit" Version="1.0.1" />
1825
<PackageVersion Include="Verify.Xunit" Version="22.5.0" />
19-
<PackageVersion Include="xunit" Version="2.6.2" />
20-
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.4" />
26+
<PackageVersion Include="xunit" Version="2.9.2" />
27+
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
2128
</ItemGroup>
2229
</Project>

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "8.0.400"
3+
"version": "9.0.100"
44
}
55
}

src/EntityFrameworkCore.Projectables/Services/ProjectableExpressionReplacer.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using System.Collections;
2-
using System.Collections.Generic;
32
using System.Diagnostics.CodeAnalysis;
4-
using System.Linq;
53
using System.Linq.Expressions;
64
using System.Reflection;
5+
using System.Runtime.CompilerServices;
76
using EntityFrameworkCore.Projectables.Extensions;
87
using Microsoft.EntityFrameworkCore.Metadata;
98
using Microsoft.EntityFrameworkCore.Query;
@@ -12,9 +11,10 @@ namespace EntityFrameworkCore.Projectables.Services
1211
{
1312
public sealed class ProjectableExpressionReplacer : ExpressionVisitor
1413
{
15-
readonly IProjectionExpressionResolver _resolver;
16-
readonly ExpressionArgumentReplacer _expressionArgumentReplacer = new();
17-
readonly Dictionary<MemberInfo, LambdaExpression?> _projectableMemberCache = new();
14+
private readonly IProjectionExpressionResolver _resolver;
15+
private readonly ExpressionArgumentReplacer _expressionArgumentReplacer = new();
16+
private readonly Dictionary<MemberInfo, LambdaExpression?> _projectableMemberCache = new();
17+
private IQueryProvider? _currentQueryProvider;
1818
private bool _disableRootRewrite;
1919
private IEntityType? _entityType;
2020

@@ -60,6 +60,9 @@ bool TryGetReflectedExpression(MemberInfo memberInfo, [NotNullWhen(true)] out La
6060
public Expression? Replace(Expression? node)
6161
{
6262
_disableRootRewrite = false;
63+
_currentQueryProvider = null;
64+
_entityType = null;
65+
6366
var ret = Visit(node);
6467

6568
if (_disableRootRewrite)
@@ -190,6 +193,29 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
190193

191194
protected override Expression VisitMember(MemberExpression node)
192195
{
196+
// Evaluate captured variables in closures that contain EF queries to inline them into the main query
197+
if (node.Expression is ConstantExpression constant &&
198+
constant.Type.Attributes.HasFlag(TypeAttributes.NestedPrivate) &&
199+
Attribute.IsDefined(constant.Type, typeof(CompilerGeneratedAttribute), inherit: true))
200+
{
201+
try
202+
{
203+
var value = Expression
204+
.Lambda<Func<object>>(Expression.Convert(node, typeof(object)))
205+
.Compile()
206+
.Invoke();
207+
208+
if (value is IQueryable queryable && ReferenceEquals(queryable.Provider, _currentQueryProvider))
209+
{
210+
return Visit(queryable.Expression);
211+
}
212+
}
213+
catch
214+
{
215+
// Ignore evaluation exceptions - continue with normal processing
216+
}
217+
}
218+
193219
var nodeExpression = node.Expression switch {
194220
UnaryExpression { NodeType: ExpressionType.Convert, Type: { IsInterface: true } type, Operand: { } operand }
195221
when type.IsAssignableFrom(operand.Type)
@@ -232,6 +258,7 @@ protected override Expression VisitExtension(Expression node)
232258
if (node is EntityQueryRootExpression root)
233259
{
234260
_entityType = root.EntityType;
261+
_currentQueryProvider = root.QueryProvider;
235262
}
236263

237264
return base.VisitExtension(node);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
DECLARE @__validArray_0 nvarchar(4000) = N'[1,2,3]';
2+
3+
SELECT [t].[Id]
4+
FROM [TestEntity] AS [t]
5+
WHERE [t].[Id] IN (
6+
SELECT [v].[value]
7+
FROM OPENJSON(@__validArray_0) WITH ([value] int '$') AS [v]
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
DECLARE @__validList_0 nvarchar(4000) = N'[1,2,3]';
2+
3+
SELECT [t].[Id]
4+
FROM [TestEntity] AS [t]
5+
WHERE [t].[Id] IN (
6+
SELECT [v].[value]
7+
FROM OPENJSON(@__validList_0) WITH ([value] int '$') AS [v]
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SELECT [t].[Id]
2+
FROM [TestEntity] AS [t]
3+
WHERE [t].[Id] IN (1, 2, 3)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
SELECT [o1].[RecordDate]
2+
FROM [User] AS [u]
3+
INNER JOIN (
4+
SELECT [o0].[RecordDate], [o0].[UserId]
5+
FROM (
6+
SELECT [o].[RecordDate], [o].[UserId], ROW_NUMBER() OVER(PARTITION BY [o].[UserId] ORDER BY [o].[RecordDate] DESC) AS [row]
7+
FROM [Order] AS [o]
8+
) AS [o0]
9+
WHERE [o0].[row] <= 2
10+
) AS [o1] ON [u].[Id] = [o1].[UserId]

0 commit comments

Comments
 (0)