├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── Directory.Build.props
├── Directory.Packages.props
├── EntityFrameworkCore.Projectables.sln
├── Key.snk
├── LICENSE.md
├── README.md
├── benchmarks
└── EntityFrameworkCore.Projectables.Benchmarks
│ ├── EntityFrameworkCore.Projectables.Benchmarks.csproj
│ ├── Helpers
│ ├── TestDbContext.cs
│ ├── TestEntity.cs
│ └── TestEntityExtensions.cs
│ ├── PlainOverhead.cs
│ ├── Program.cs
│ ├── ProjectableExtensionMethods.cs
│ ├── ProjectableMethods.cs
│ └── ProjectableProperties.cs
├── global.json
├── samples
└── ReadmeSample
│ ├── ApplicationDbContext.cs
│ ├── Entities
│ ├── Order.cs
│ ├── OrderItem.cs
│ ├── Product.cs
│ └── User.cs
│ ├── Extensions
│ └── UserExtensions.cs
│ ├── Program.cs
│ └── ReadmeSample.csproj
├── src
├── Directory.Build.props
├── EntityFrameworkCore.Projectables.Abstractions
│ ├── EntityFrameworkCore.Projectables.Abstractions.csproj
│ ├── NullConditionalRewriteSupport.cs
│ └── ProjectableAttribute.cs
├── EntityFrameworkCore.Projectables.Generator
│ ├── AnalyzerReleases.Shipped.md
│ ├── AnalyzerReleases.Unshipped.md
│ ├── DeclarationSyntaxRewriter.cs
│ ├── Diagnostics.cs
│ ├── EntityFrameworkCore.Projectables.Generator.csproj
│ ├── ExpressionSyntaxRewriter.cs
│ ├── MemberDeclarationSyntaxAndCompilationEqualityComparer.cs
│ ├── MemberDeclarationSyntaxEqualityComparer.cs
│ ├── ProjectableDescriptor.cs
│ ├── ProjectableInterpreter.cs
│ ├── ProjectionExpressionGenerator.cs
│ └── VariableReplacementRewriter.cs
└── EntityFrameworkCore.Projectables
│ ├── EntityFrameworkCore.Projectables.csproj
│ ├── Extensions
│ ├── DbContextOptionsExtensions.cs
│ ├── ExpressionExtensions.cs
│ ├── QueryableExtensions.cs
│ └── TypeExtensions.cs
│ ├── Infrastructure
│ ├── CompatibilityMode.cs
│ ├── Internal
│ │ ├── CustomConventionSetPlugin.cs
│ │ ├── CustomQueryCompiler.cs
│ │ ├── CustomQueryTranslationPreprocessor.cs
│ │ ├── CustomQueryTranslationPreprocessorFactory.cs
│ │ ├── ProjectablePropertiesNotMappedConvention.cs
│ │ ├── ProjectablePropertiesNotMappedConventionPlugin.cs
│ │ ├── ProjectablesExpandQueryFiltersConvention.cs
│ │ └── ProjectionOptionsExtension.cs
│ └── ProjectableOptionsBuilder.cs
│ └── Services
│ ├── ExpressionArgumentReplacer.cs
│ ├── IProjectionExpressionResolver.cs
│ ├── ProjectableExpressionReplacer.cs
│ ├── ProjectionExpressionClassNameGenerator.cs
│ └── ProjectionExpressionResolver.cs
└── tests
├── EntityFrameworkCore.Projectables.FunctionalTests
├── ChangeTrackerTests.cs
├── ComplexArgumentsTests.ArrayOfPrimitivesArguments.DotNet9_0.verified.txt
├── ComplexArgumentsTests.ArrayOfPrimitivesArguments.verified.txt
├── ComplexArgumentsTests.ListOfPrimitivesArguments.DotNet9_0.verified.txt
├── ComplexArgumentsTests.ListOfPrimitivesArguments.verified.txt
├── ComplexArgumentsTests.ParamsOfPrimitivesArguments.DotNet9_0.verified.txt
├── ComplexArgumentsTests.ParamsOfPrimitivesArguments.verified.txt
├── ComplexArgumentsTests.SupportsListArguments.verified.txt
├── ComplexArgumentsTests.cs
├── ComplexModelTests.ProjectOverCollectionNavigationProperty.DotNet9_0.verified.txt
├── ComplexModelTests.ProjectOverCollectionNavigationProperty.verified.txt
├── ComplexModelTests.ProjectOverMethodTakingDbContext.DotNet9_0.verified.txt
├── ComplexModelTests.ProjectOverMethodTakingDbContext.verified.txt
├── ComplexModelTests.ProjectOverNavigationProperty.DotNet9_0.verified.txt
├── ComplexModelTests.ProjectOverNavigationProperty.verified.txt
├── ComplexModelTests.ProjectQueryFilters.verified.txt
├── ComplexModelTests.cs
├── DefaultValueTests.ExplicitDefaultValueIsSupported.DotNet9_0.verified.txt
├── DefaultValueTests.ExplicitDefaultValueIsSupported.verified.txt
├── DefaultValueTests.cs
├── EntityFrameworkCore.Projectables.FunctionalTests.csproj
├── EnumerableProjectableTests.cs
├── ExtensionsMethods
│ ├── Entity.cs
│ ├── EntityExtensions.cs
│ ├── ExtensionMethodTests.ExtensionMethodAcceptingDbContext.DotNet9_0.verified.txt
│ ├── ExtensionMethodTests.ExtensionMethodAcceptingDbContext.verified.txt
│ ├── ExtensionMethodTests.ExtensionOnPrimitive.DotNet9_0.verified.txt
│ ├── ExtensionMethodTests.ExtensionOnPrimitive.verified.txt
│ ├── ExtensionMethodTests.SelectProjectableExtensionMethod.DotNet9_0.verified.txt
│ ├── ExtensionMethodTests.SelectProjectableExtensionMethod.verified.txt
│ ├── ExtensionMethodTests.SelectProjectableExtensionMethod2.DotNet9_0.verified.txt
│ ├── ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt
│ └── ExtensionMethodTests.cs
├── Generics
│ ├── Entity.cs
│ ├── EntityExtensions.cs
│ ├── GenericEntityTests.HasMatchingStringKeyConversion_GetsTranslated.DotNet9_0.verified.txt
│ ├── GenericEntityTests.HasMatchingStringKeyConversion_GetsTranslated.verified.txt
│ ├── GenericEntityTests.cs
│ ├── GenericExtensionMethodTests.cs
│ ├── GenericFunctionTests.DefaultIfIdIsNegative.DotNet9_0.verified.txt
│ ├── GenericFunctionTests.DefaultIfIdIsNegative.verified.txt
│ ├── GenericFunctionTests.QueryOrderedByDefault.verified.txt
│ ├── IEntity.cs
│ ├── MultipleGenericsTests.TestMultipleArguments.DotNet9_0.verified.txt
│ ├── MultipleGenericsTests.TestMultipleArguments.verified.txt
│ └── MultipleGenericsTests.cs
├── Helpers
│ ├── SampleDbContext.cs
│ └── SampleUserWithGlobalQueryFilterDbContext.cs
├── InheritedMembersTests.ProjectOverMethodTakingDbContext.DotNet9_0.verified.txt
├── InheritedMembersTests.ProjectOverMethodTakingDbContext.verified.txt
├── InheritedMembersTests.cs
├── InheritedModelTests.ProjectOverExtensionMethod.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverExtensionMethod.verified.txt
├── InheritedModelTests.ProjectOverImplementedMethod.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverImplementedMethod.verified.txt
├── InheritedModelTests.ProjectOverImplementedProperty.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverImplementedProperty.verified.txt
├── InheritedModelTests.ProjectOverInheritedMethodImplementation.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverInheritedMethodImplementation.verified.txt
├── InheritedModelTests.ProjectOverInheritedPropertyImplementation.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverInheritedPropertyImplementation.verified.txt
├── InheritedModelTests.ProjectOverOverriddenMethodImplementation.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverOverriddenMethodImplementation.verified.txt
├── InheritedModelTests.ProjectOverOverriddenPropertyImplementation.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverOverriddenPropertyImplementation.verified.txt
├── InheritedModelTests.ProjectOverProvider.DotNet9_0.verified.txt
├── InheritedModelTests.ProjectOverProvider.verified.txt
├── InheritedModelTests.cs
├── MethodGroupTests.ProjectOverMethodGroup.DotNet9_0.verified.txt
├── MethodGroupTests.ProjectOverMethodGroup.verified.txt
├── MethodGroupTests.cs
├── ModuleInitializer.cs
├── NameSyntaxTests.QualifiedNameSyntaxTest.DotNet9_0.verified.txt
├── NameSyntaxTests.QualifiedNameSyntaxTest.verified.txt
├── NameSyntaxTests.cs
├── NullConditionals
│ ├── Entity.cs
│ ├── EntityExtensions.cs
│ ├── IngoreNullConditionalRewriteTests.ComplexMemberExpression.DotNet9_0.verified.txt
│ ├── IngoreNullConditionalRewriteTests.ComplexMemberExpression.verified.txt
│ ├── IngoreNullConditionalRewriteTests.RelationalExpression.DotNet9_0.verified.txt
│ ├── IngoreNullConditionalRewriteTests.RelationalExpression.verified.txt
│ ├── IngoreNullConditionalRewriteTests.SimpleMemberExpression.DotNet9_0.verified.txt
│ ├── IngoreNullConditionalRewriteTests.SimpleMemberExpression.verified.txt
│ ├── IngoreNullConditionalRewriteTests.cs
│ ├── RewriteNullConditionalRewriteTests.ComplexMemberExpression.DotNet9_0.verified.txt
│ ├── RewriteNullConditionalRewriteTests.ComplexMemberExpression.verified.txt
│ ├── RewriteNullConditionalRewriteTests.RelationalExpression.DotNet9_0.verified.txt
│ ├── RewriteNullConditionalRewriteTests.RelationalExpression.verified.txt
│ ├── RewriteNullConditionalRewriteTests.SimpleMemberExpression.DotNet9_0.verified.txt
│ ├── RewriteNullConditionalRewriteTests.SimpleMemberExpression.verified.txt
│ └── RewriteNullConditionalRewriteTests.cs
├── PrivateProjectables.Issue63Repro.DotNet9_0.verified.txt
├── PrivateProjectables.Issue63Repro.verified.txt
├── PrivateProjectables.cs
├── QueryRootTests.AsNoTrackingQueryRootExpression.DotNet9_0.verified.txt
├── QueryRootTests.AsNoTrackingQueryRootExpression.verified.txt
├── QueryRootTests.AsTrackingQueryRootExpression.DotNet9_0.verified.txt
├── QueryRootTests.AsTrackingQueryRootExpression.verified.txt
├── QueryRootTests.DontUseMemberPropertyQueryRootExpression.DotNet9_0.verified.txt
├── QueryRootTests.DontUseMemberPropertyQueryRootExpression.verified.txt
├── QueryRootTests.EntityRootSubqueryExpression.DotNet9_0.verified.txt
├── QueryRootTests.EntityRootSubqueryExpression.verified.txt
├── QueryRootTests.UseMemberPropertyQueryRootExpression.DotNet9_0.verified.txt
├── QueryRootTests.UseMemberPropertyQueryRootExpression.verified.txt
├── QueryRootTests.cs
├── StatefullComplexFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StatefullComplexFunctionTests.FilterOnProjectableProperty.verified.txt
├── StatefullComplexFunctionTests.PassInReferenceArguments.DotNet9_0.verified.txt
├── StatefullComplexFunctionTests.PassInReferenceArguments.verified.txt
├── StatefullComplexFunctionTests.PassInVariableArguments.DotNet9_0.verified.txt
├── StatefullComplexFunctionTests.PassInVariableArguments.verified.txt
├── StatefullComplexFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── StatefullComplexFunctionTests.SelectProjectableProperty.verified.txt
├── StatefullComplexFunctionTests.cs
├── StatefullPropertyTests.CombineSelectProjectableProperties.DotNet9_0.verified.txt
├── StatefullPropertyTests.CombineSelectProjectableProperties.verified.txt
├── StatefullPropertyTests.FilterOnComplexProjectableProperty.DotNet9_0.verified.txt
├── StatefullPropertyTests.FilterOnComplexProjectableProperty.verified.txt
├── StatefullPropertyTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StatefullPropertyTests.FilterOnProjectableProperty.verified.txt
├── StatefullPropertyTests.SelectComplexProjectableProperty.DotNet9_0.verified.txt
├── StatefullPropertyTests.SelectComplexProjectableProperty.verified.txt
├── StatefullPropertyTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── StatefullPropertyTests.SelectProjectableProperty.verified.txt
├── StatefullPropertyTests.cs
├── StatefullSimpleFunctionTests.CombineSelectProjectableProperties.DotNet9_0.verified.txt
├── StatefullSimpleFunctionTests.CombineSelectProjectableProperties.verified.txt
├── StatefullSimpleFunctionTests.FilterOnComplexProjectableProperty.DotNet9_0.verified.txt
├── StatefullSimpleFunctionTests.FilterOnComplexProjectableProperty.verified.txt
├── StatefullSimpleFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StatefullSimpleFunctionTests.FilterOnProjectableProperty.verified.txt
├── StatefullSimpleFunctionTests.SelectComplexProjectableProperty.DotNet9_0.verified.txt
├── StatefullSimpleFunctionTests.SelectComplexProjectableProperty.verified.txt
├── StatefullSimpleFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── StatefullSimpleFunctionTests.SelectProjectableProperty.verified.txt
├── StatefullSimpleFunctionTests.cs
├── StatelessComplexFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StatelessComplexFunctionTests.FilterOnProjectableProperty.verified.txt
├── StatelessComplexFunctionTests.PassInVariableArguments.DotNet9_0.verified.txt
├── StatelessComplexFunctionTests.PassInVariableArguments.verified.txt
├── StatelessComplexFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── StatelessComplexFunctionTests.SelectProjectableProperty.verified.txt
├── StatelessComplexFunctionTests.cs
├── StatelessPropertyTests.FilterOnProjectableProperty.verified.txt
├── StatelessPropertyTests.SelectProjectableProperty.verified.txt
├── StatelessSimpleFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StatelessSimpleFunctionTests.FilterOnProjectableProperty.verified.txt
├── StatelessSimpleFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── StatelessSimpleFunctionTests.SelectProjectableProperty.verified.txt
├── StatelessSimpleFunctionTests.cs
├── StaticMembersTests.FilterOnProjectableProperty.DotNet9_0.verified.txt
├── StaticMembersTests.FilterOnProjectableProperty.verified.txt
├── StaticMembersTests.cs
├── TypeNameQualificationTests.SelectProjectableProperty.DotNet9_0.verified.txt
├── TypeNameQualificationTests.SelectProjectableProperty.verified.txt
├── TypeNameQualificationTests.cs
├── UseMemberBodyPropertyTests.UseMemberPropertyExpression.DotNet9_0.verified.txt
├── UseMemberBodyPropertyTests.UseMemberPropertyExpression.verified.txt
├── UseMemberBodyPropertyTests.UseMemberPropertyGenerated.DotNet9_0.verified.txt
├── UseMemberBodyPropertyTests.UseMemberPropertyGenerated.verified.txt
└── UseMemberBodyPropertyTests.cs
├── EntityFrameworkCore.Projectables.Generator.Tests
├── EntityFrameworkCore.Projectables.Generator.Tests.csproj
├── ProjectionExpressionGeneratorTests.ArgumentlessProjectableComputedMethod.verified.txt
├── ProjectionExpressionGeneratorTests.BaseMemberExplicitReference.verified.txt
├── ProjectionExpressionGeneratorTests.BaseMemberImplicitReference.verified.txt
├── ProjectionExpressionGeneratorTests.BaseMethodExplicitReference.verified.txt
├── ProjectionExpressionGeneratorTests.BaseMethorImplicitReference.verified.txt
├── ProjectionExpressionGeneratorTests.BooleanSimpleTernary_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.Cast.verified.txt
├── ProjectionExpressionGeneratorTests.ConstMember.verified.txt
├── ProjectionExpressionGeneratorTests.ConstMember2.verified.txt
├── ProjectionExpressionGeneratorTests.ConstMember3.verified.txt
├── ProjectionExpressionGeneratorTests.DeclarationTypeNamesAreGettingFullyQualified.verified.txt
├── ProjectionExpressionGeneratorTests.DefaultValuesGetRemoved.verified.txt
├── ProjectionExpressionGeneratorTests.EnumAccessor.verified.txt
├── ProjectionExpressionGeneratorTests.FooOrBar.verified.txt
├── ProjectionExpressionGeneratorTests.GenericClassesWithContraints_AreRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.GenericClassesWithTypeContraints_AreRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.GenericMethods_AreRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.GenericNullableReferenceTypesAreBeingEliminated.verified.txt
├── ProjectionExpressionGeneratorTests.GenericTypes.verified.txt
├── ProjectionExpressionGeneratorTests.GenericTypesWithConstraints.verified.txt
├── ProjectionExpressionGeneratorTests.InheritedMembers.verified.txt
├── ProjectionExpressionGeneratorTests.IsOperator.verified.txt
├── ProjectionExpressionGeneratorTests.MinimalProjectableComputedProperty.verified.txt
├── ProjectionExpressionGeneratorTests.MixPrimaryConstructorAndProperties.verified.txt
├── ProjectionExpressionGeneratorTests.MoreComplexProjectableComputedProperty.verified.txt
├── ProjectionExpressionGeneratorTests.NavigationProperties.verified.txt
├── ProjectionExpressionGeneratorTests.NullConditionalNullCoalesceTypeConversion.verified.txt
├── ProjectionExpressionGeneratorTests.NullableElementAndMemberBinding_WithIgnoreSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableElementAndMemberBinding_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableElementBinding_WithIgnoreSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableElementBinding_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableMemberBinding_WithIgnoreSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableMemberBinding_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableParameters_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableReferenceTypeCastOperatorGetsEliminated.verified.txt
├── ProjectionExpressionGeneratorTests.NullableReferenceTypesAreBeingEliminated.verified.txt
├── ProjectionExpressionGeneratorTests.NullableSimpleElementBinding_WithIgnoreSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableSimpleElementBinding_WithRewriteSupport_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.NullableValueCastOperatorsPersist.verified.txt
├── ProjectionExpressionGeneratorTests.ParamsModifiedGetsRemoved.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableComputedMethodWithMultipleArguments.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableComputedMethodWithSingleArgument.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableComputedPropertyMethod.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableComputedPropertyUsingThis.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableExtensionMethod.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableExtensionMethod2.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.verified.txt
├── ProjectionExpressionGeneratorTests.ProjectablePropertyToNavigationalProperty.verified.txt
├── ProjectionExpressionGeneratorTests.RelationalProperty.verified.txt
├── ProjectionExpressionGeneratorTests.RequiredNamespace.verified.txt
├── ProjectionExpressionGeneratorTests.SimpleProjectableComputedInNestedClassProperty.verified.txt
├── ProjectionExpressionGeneratorTests.SimpleProjectableComputedProperty.verified.txt
├── ProjectionExpressionGeneratorTests.SimpleProjectableMethod.verified.txt
├── ProjectionExpressionGeneratorTests.SimpleProjectableProperty.verified.txt
├── ProjectionExpressionGeneratorTests.StaticMembers.verified.txt
├── ProjectionExpressionGeneratorTests.StaticMembers2.verified.txt
├── ProjectionExpressionGeneratorTests.StaticMethodWithNoParameters.verified.txt
├── ProjectionExpressionGeneratorTests.StaticMethodWithParameters.verified.txt
├── ProjectionExpressionGeneratorTests.StringInterpolationWithParenthesis_NoParenthesisAdded.verified.txt
├── ProjectionExpressionGeneratorTests.StringInterpolationWithStaticCall_IsBeingRewritten.verified.txt
├── ProjectionExpressionGeneratorTests.SwitchExpressionWithConstantPattern.verified.txt
├── ProjectionExpressionGeneratorTests.SwitchExpressionWithTypePattern.verified.txt
├── ProjectionExpressionGeneratorTests.TypesInBodyGetsFullyQualified.verified.txt
└── ProjectionExpressionGeneratorTests.cs
└── EntityFrameworkCore.Projectables.Tests
├── EntityFrameworkCore.Projectables.Tests.csproj
├── Extensions
└── TypeExtensionTests.cs
└── Services
├── ExpressionArgumentReplacerTests.cs
├── ProjectableExpressionReplacerTests.cs
└── ProjectionExpressionClassNameGeneratorTests.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 |
2 | name: .NET
3 |
4 | on:
5 | push:
6 | branches: [ master ]
7 | pull_request:
8 | branches: [ master ]
9 |
10 | env:
11 | # Stop wasting time caching packages
12 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
13 | # Disable sending usage data to Microsoft
14 | DOTNET_CLI_TELEMETRY_OPTOUT: true
15 | # GitHub Packages Feed settings
16 | GITHUB_FEED: https://nuget.pkg.github.com/koenbeuk/
17 | GITHUB_USER: koenbeuk
18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 |
20 | jobs:
21 | build:
22 | runs-on: ${{ matrix.os }}
23 | strategy:
24 | matrix:
25 | os: [ubuntu-latest, windows-latest, macOS-latest]
26 |
27 | steps:
28 | - uses: actions/checkout@v2
29 | - name: Setup .NET
30 | uses: actions/setup-dotnet@v1
31 | with:
32 | dotnet-version: |
33 | 8.0.x
34 | 9.0.x
35 | - name: Restore dependencies
36 | run: dotnet restore
37 | - name: Build
38 | run: dotnet build --no-restore
39 | - name: Test
40 | run: dotnet test --no-build --verbosity normal
41 |
42 | prerelease:
43 | needs: build
44 | if: github.ref == 'refs/heads/master'
45 | runs-on: ubuntu-latest
46 | steps:
47 | - uses: actions/checkout@v2
48 | - name: Setup .NET
49 | uses: actions/setup-dotnet@v1
50 | with:
51 | dotnet-version: 9.0.x
52 | - name: Pack
53 | run: |
54 | dotnet pack -v normal -c Debug --include-symbols --include-source -p:PackageVersion=4.0.0-pre-$GITHUB_RUN_ID -o nupkg
55 | - name: Push to GitHub Feed
56 | run: |
57 | for f in ./nupkg/*.nupkg
58 | do
59 | dotnet nuget push $f --source $GITHUB_FEED --api-key ${{github.token}} --skip-duplicate --no-symbols
60 | done
61 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | release:
5 | types:
6 | - published
7 |
8 | env:
9 | # Stop wasting time caching packages
10 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
11 | # Disable sending usage data to Microsoft
12 | DOTNET_CLI_TELEMETRY_OPTOUT: true
13 | # GitHub Packages Feed settings
14 | GITHUB_FEED: https://nuget.pkg.github.com/koenbeuk/
15 | GITHUB_USER: koenbeuk
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 | # Official NuGet Feed settings
18 | NUGET_FEED: https://api.nuget.org/v3/index.json
19 | NUGET_KEY: ${{ secrets.NUGET_KEY }}
20 |
21 | jobs:
22 | deploy:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v2
26 | - name: Setup .NET Core
27 | uses: actions/setup-dotnet@v1
28 | with:
29 | dotnet-version: 9.0.x
30 | include-prerelease: True
31 | - name: Create Release NuGet package
32 | run: |
33 | arrTag=(${GITHUB_REF//\// })
34 | VERSION="${arrTag[2]}"
35 | echo Version: $VERSION
36 | CONFIGURATION="Release"
37 | VERSION="${VERSION#v}"
38 | echo Clean Version: $VERSION
39 | echo Configuration: $CONFIGURATION
40 | dotnet pack -v normal -c $CONFIGURATION --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg
41 | - name: Push to GitHub Feed
42 | run: |
43 | for f in ./nupkg/*.nupkg
44 | do
45 | dotnet nuget push $f --source $GITHUB_FEED --api-key ${{github.token}} --skip-duplicate --no-symbols
46 | done
47 | - name: Push to NuGet Feed
48 | run: |
49 | for f in ./nupkg/*.nupkg
50 | do
51 | dotnet nuget push $f --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
52 | done
53 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | true
5 | 12.0
6 | enable
7 | true
8 | CS1591
9 | false
10 | enable
11 |
12 |
13 |
14 | Koen Bekkenutte
15 | MIT
16 | https://github.com/koenbeuk/EntityFrameworkCore.Projectables
17 | https://github.com/koenbeuk/EntityFrameworkCore.Projectables.git
18 | git
19 | https://github.com/koenbeuk/EntityFrameworkCore.Projectables/releases
20 | Project over properties and functions in your linq queries
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koenbeuk/EntityFrameworkCore.Projectables/552908d6b0923d39808af676ae6d4d3707389cf6/Key.snk
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Project Author
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/EntityFrameworkCore.Projectables.Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/Helpers/TestDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.EntityFrameworkCore;
7 | using EntityFrameworkCore.Projectables.Extensions;
8 | using EntityFrameworkCore.Projectables.Infrastructure;
9 |
10 | namespace EntityFrameworkCore.Projectables.Benchmarks.Helpers
11 | {
12 | class TestDbContext : DbContext
13 | {
14 | readonly bool _useProjectables;
15 | readonly bool _useFullCompatibiltyMode;
16 |
17 | public TestDbContext(bool useProjectables, bool useFullCompatibiltyMode = true)
18 | {
19 | _useProjectables = useProjectables;
20 | _useFullCompatibiltyMode = useFullCompatibiltyMode;
21 | }
22 |
23 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
24 | {
25 | optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=ReadmeSample;Trusted_Connection=True");
26 |
27 | if (_useProjectables)
28 | {
29 | optionsBuilder.UseProjectables(projectableOptions => {
30 | projectableOptions.CompatibilityMode(_useFullCompatibiltyMode ? CompatibilityMode.Full : CompatibilityMode.Limited);
31 | });
32 | }
33 | }
34 |
35 | public DbSet Entities => Set();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/Helpers/TestEntity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EntityFrameworkCore.Projectables.Benchmarks.Helpers
8 | {
9 | public class TestEntity
10 | {
11 | public int Id { get; set; }
12 |
13 | [Projectable]
14 | public int IdPlus1 => Id + 1;
15 |
16 | [Projectable]
17 | public int IdPlus1Method() => Id + 1;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/Helpers/TestEntityExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EntityFrameworkCore.Projectables.Benchmarks.Helpers
8 | {
9 | public static class TestEntityExtensions
10 | {
11 | public static int IdPlus1ExtensionMethod(this TestEntity entity) => entity.Id + 1;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/PlainOverhead.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO.Compression;
3 | using System.Linq;
4 | using BenchmarkDotNet.Attributes;
5 | using EntityFrameworkCore.Projectables.Benchmarks.Helpers;
6 | using EntityFrameworkCore.Projectables.Extensions;
7 | using EntityFrameworkCore.Projectables.Infrastructure;
8 | using Microsoft.EntityFrameworkCore;
9 |
10 | namespace EntityFrameworkCore.Projectables.Benchmarks
11 | {
12 | public class PlainOverhead
13 | {
14 | [Benchmark(Baseline = true)]
15 | public void WithoutProjectables()
16 | {
17 | using var dbContext = new TestDbContext(false);
18 |
19 | for (int i = 0; i < 10000; i++)
20 | {
21 | dbContext.Entities.Select(x => x.Id).ToQueryString();
22 | }
23 | }
24 |
25 | [Benchmark]
26 | public void WithProjectablesWithFullCompatibility()
27 | {
28 | using var dbContext = new TestDbContext(true);
29 |
30 | for (int i = 0; i < 10000; i++)
31 | {
32 | dbContext.Entities.Select(x => x.Id).ToQueryString();
33 | }
34 | }
35 |
36 |
37 | [Benchmark]
38 | public void WithProjectablesWithLimitedCompatibility()
39 | {
40 | using var dbContext = new TestDbContext(true, false);
41 |
42 | for (int i = 0; i < 10000; i++)
43 | {
44 | dbContext.Entities.Select(x => x.Id).ToQueryString();
45 | }
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/Program.cs:
--------------------------------------------------------------------------------
1 | using BenchmarkDotNet.Configs;
2 | using BenchmarkDotNet.Running;
3 | using EntityFrameworkCore.Projectables.Benchmarks;
4 |
5 | BenchmarkSwitcher.FromAssembly(typeof(PlainOverhead).Assembly).Run(args, DefaultConfig.Instance.WithOption(ConfigOptions.DisableOptimizationsValidator, true));
6 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/ProjectableExtensionMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using BenchmarkDotNet.Attributes;
7 | using EntityFrameworkCore.Projectables.Benchmarks.Helpers;
8 | using Microsoft.EntityFrameworkCore;
9 |
10 | namespace EntityFrameworkCore.Projectables.Benchmarks
11 | {
12 | public class ProjectableExtensionMethods
13 | {
14 | const int innerLoop = 10000;
15 |
16 | [Benchmark(Baseline = true)]
17 | public void WithoutProjectables()
18 | {
19 | using var dbContext = new TestDbContext(false);
20 |
21 | for (int i = 0; i < innerLoop; i++)
22 | {
23 | dbContext.Entities.Select(x => x.Id + 1).ToQueryString();
24 | }
25 | }
26 |
27 | [Benchmark]
28 | public void WithProjectablesWithFullCompatibility()
29 | {
30 | using var dbContext = new TestDbContext(true);
31 |
32 | for (int i = 0; i < innerLoop; i++)
33 | {
34 | dbContext.Entities.Select(x => x.IdPlus1Method()).ToQueryString();
35 | }
36 | }
37 |
38 | [Benchmark]
39 | public void WithProjectablesWithLimitedCompatibility()
40 | {
41 | using var dbContext = new TestDbContext(true, false);
42 |
43 | for (int i = 0; i < innerLoop; i++)
44 | {
45 | dbContext.Entities.Select(x => x.IdPlus1Method()).ToQueryString();
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/ProjectableMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using BenchmarkDotNet.Attributes;
4 | using EntityFrameworkCore.Projectables.Benchmarks.Helpers;
5 | using EntityFrameworkCore.Projectables.Extensions;
6 | using EntityFrameworkCore.Projectables.Infrastructure;
7 | using Microsoft.EntityFrameworkCore;
8 |
9 | namespace EntityFrameworkCore.Projectables.Benchmarks
10 | {
11 | public class ProjectableMethods
12 | {
13 | const int innerLoop = 10000;
14 |
15 | [Benchmark(Baseline = true)]
16 | public void WithoutProjectables()
17 | {
18 | using var dbContext = new TestDbContext(false);
19 |
20 | for (int i = 0; i < innerLoop; i++)
21 | {
22 | dbContext.Entities.Select(x => x.Id + 1).ToQueryString();
23 | }
24 | }
25 |
26 | [Benchmark]
27 | public void WithProjectablesWithFullCompatibility()
28 | {
29 | using var dbContext = new TestDbContext(true);
30 |
31 | for (int i = 0; i < innerLoop; i++)
32 | {
33 | dbContext.Entities.Select(x => x.IdPlus1Method()).ToQueryString();
34 | }
35 | }
36 |
37 | [Benchmark]
38 | public void WithProjectablesWithLimitedCompatibility()
39 | {
40 | using var dbContext = new TestDbContext(true, false);
41 |
42 | for (int i = 0; i < innerLoop; i++)
43 | {
44 | dbContext.Entities.Select(x => x.IdPlus1Method()).ToQueryString();
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/benchmarks/EntityFrameworkCore.Projectables.Benchmarks/ProjectableProperties.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using BenchmarkDotNet.Attributes;
4 | using EntityFrameworkCore.Projectables.Benchmarks.Helpers;
5 | using EntityFrameworkCore.Projectables.Extensions;
6 | using EntityFrameworkCore.Projectables.Infrastructure;
7 | using Microsoft.EntityFrameworkCore;
8 |
9 | namespace EntityFrameworkCore.Projectables.Benchmarks
10 | {
11 | public class ProjectableProperties
12 | {
13 | const int innerLoop = 10000;
14 |
15 | [Benchmark(Baseline = true)]
16 | public void WithoutProjectables()
17 | {
18 | using var dbContext = new TestDbContext(false);
19 |
20 | for (int i = 0; i < innerLoop; i++)
21 | {
22 | if (1 == i)
23 | throw new Exception(dbContext.Entities.Select(x => x.Id + 1).ToQueryString());
24 | }
25 | }
26 |
27 | [Benchmark]
28 | public void WithProjectablesWithFullCompatibility()
29 | {
30 | using var dbContext = new TestDbContext(true);
31 |
32 | for (int i = 0; i < innerLoop; i++)
33 | {
34 | dbContext.Entities.Select(x => x.IdPlus1).ToQueryString();
35 | }
36 | }
37 |
38 | [Benchmark]
39 | public void WithProjectablesWithLimitedCompatibility()
40 | {
41 | using var dbContext = new TestDbContext(true, false);
42 |
43 | for (int i = 0; i < innerLoop; i++)
44 | {
45 | dbContext.Entities.Select(x => x.IdPlus1).ToQueryString();
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.100",
4 | "rollForward": "latestMinor"
5 | }
6 | }
--------------------------------------------------------------------------------
/samples/ReadmeSample/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Cryptography.X509Certificates;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.Extensions;
8 | using Microsoft.EntityFrameworkCore;
9 | using ReadmeSample.Entities;
10 |
11 | namespace ReadmeSample
12 | {
13 | public class ApplicationDbContext : DbContext
14 | {
15 | public DbSet Users { get; set; }
16 | public DbSet Products { get; set; }
17 | public DbSet Orders { get; set; }
18 |
19 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
20 | {
21 | optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=ReadmeSample;Trusted_Connection=True");
22 | optionsBuilder.UseProjectables();
23 | }
24 |
25 | protected override void OnModelCreating(ModelBuilder modelBuilder)
26 | {
27 | modelBuilder.Entity().HasKey(x => new { x.OrderId, x.ProductId });
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Entities/Order.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables;
7 |
8 | namespace ReadmeSample.Entities
9 | {
10 | public class Order
11 | {
12 | public int Id { get; set; }
13 | public int UserId { get; set; }
14 | public DateTime CreatedDate { get; set; }
15 | public DateTime? FulfilledDate { get; set; }
16 |
17 | public decimal TaxRate { get; set; }
18 |
19 | public User User { get; set; }
20 | public ICollection Items { get; set; }
21 |
22 | [Projectable] public decimal Subtotal => Items.Sum(item => item.Product.ListPrice * item.Quantity);
23 | [Projectable] public decimal Tax => Subtotal * TaxRate;
24 | [Projectable] public decimal GrandTotal => Subtotal * TaxRate;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Entities/OrderItem.cs:
--------------------------------------------------------------------------------
1 | namespace ReadmeSample.Entities
2 | {
3 | public class OrderItem
4 | {
5 | public int OrderId { get; set; }
6 | public int ProductId { get; set; }
7 | public int Quantity { get; set; }
8 |
9 | public Order Order { get; set; }
10 | public Product Product { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Entities/Product.cs:
--------------------------------------------------------------------------------
1 | namespace ReadmeSample.Entities
2 | {
3 | public class Product
4 | {
5 | public int Id { get; set; }
6 |
7 | public string Name { get; set; }
8 |
9 | public decimal ListPrice { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Entities/User.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 |
4 | namespace ReadmeSample.Entities
5 | {
6 | public class User
7 | {
8 | public int Id { get; set; }
9 |
10 | public string UserName { get; set; }
11 |
12 | public string EmailAddress { get; set; }
13 |
14 | public ICollection Orders { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Extensions/UserExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables;
7 | using ReadmeSample.Entities;
8 |
9 | namespace ReadmeSample.Extensions
10 | {
11 | public static class UserExtensions
12 | {
13 | [Projectable]
14 | public static Order GetMostRecentOrderForUser(this User user, bool includeUnfulfilled) =>
15 | user.Orders
16 | .Where(x => !includeUnfulfilled ? x .FulfilledDate != null : true)
17 | .OrderByDescending(x => x.CreatedDate)
18 | .FirstOrDefault();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/Program.cs:
--------------------------------------------------------------------------------
1 | using ReadmeSample;
2 | using ReadmeSample.Entities;
3 | using ReadmeSample.Extensions;
4 |
5 | using var dbContext = new ApplicationDbContext();
6 |
7 | // recreate database
8 | dbContext.Database.EnsureDeleted();
9 | dbContext.Database.EnsureCreated();
10 |
11 | // Populate with seed data
12 | var sampleUser = new User { UserName = "Jon", EmailAddress = "jon@doe.com" };
13 | var sampleProduct = new Product { Name = "Blue Pen", ListPrice = 1.5m };
14 | var sampleOrder = new Order {
15 | User = sampleUser,
16 | TaxRate = .19m,
17 | CreatedDate = DateTime.UtcNow.AddDays(-1),
18 | FulfilledDate = DateTime.UtcNow,
19 | Items = new List {
20 | new OrderItem { Product = sampleProduct, Quantity = 5 }
21 | }
22 | };
23 |
24 | dbContext.AddRange(sampleUser, sampleProduct, sampleOrder);
25 | dbContext.SaveChanges();
26 |
27 | var query = dbContext.Users
28 | .Where(x => x.UserName == sampleUser.UserName)
29 | .Select(x => new {
30 | GrandTotal = x.GetMostRecentOrderForUser(/* includeUnfulfilled: */ false).GrandTotal
31 | });
32 |
33 | var result = query.First();
34 |
35 | Console.WriteLine($"Jons latest order had a grant total of {result.GrandTotal}");
36 |
--------------------------------------------------------------------------------
/samples/ReadmeSample/ReadmeSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | disable
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | snupkg
7 |
8 |
9 |
10 | true
11 | ../../Key.snk
12 |
13 |
14 |
15 | true
16 | true
17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
18 |
19 |
20 |
21 | true
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Abstractions/EntityFrameworkCore.Projectables.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EntityFrameworkCore.Projectables
5 | README.md
6 |
7 |
8 |
9 |
10 | false
11 | Content
12 | PreserveNewest
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Abstractions/NullConditionalRewriteSupport.cs:
--------------------------------------------------------------------------------
1 | namespace EntityFrameworkCore.Projectables
2 | {
3 | ///
4 | /// Configures how null-conditional operators are handeled
5 | ///
6 | public enum NullConditionalRewriteSupport
7 | {
8 | ///
9 | /// Don't rewrite null conditional operators (Default behavior).
10 | /// Usage of null conditional operators is thereby not allowed
11 | ///
12 | None,
13 |
14 | ///
15 | /// Ignore null-conditional operators in the generated expression tree
16 | ///
17 | ///
18 | /// (A?.B) is rewritten as expression: (A.B)
19 | ///
20 | Ignore,
21 |
22 | ///
23 | /// Translates null-conditional operators into explicit null checks
24 | ///
25 | ///
26 | /// (A?.B) is rewritten as expression: (A != null ? A.B : null)
27 | ///
28 | Rewrite
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Abstractions/ProjectableAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EntityFrameworkCore.Projectables
8 | {
9 | ///
10 | /// Declares this property or method to be Projectable.
11 | /// A companion Expression tree will be generated
12 | ///
13 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
14 | public sealed class ProjectableAttribute : Attribute
15 | {
16 | ///
17 | /// Get or set how null-conditional operators are handeled
18 | ///
19 | public NullConditionalRewriteSupport NullConditionalRewriteSupport { get; set; }
20 |
21 | ///
22 | /// Get or set from which member to get the expression,
23 | /// or null to get it from the current member.
24 | ///
25 | public string? UseMemberBody { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/AnalyzerReleases.Shipped.md:
--------------------------------------------------------------------------------
1 | ## Release 5.0
2 |
3 | ### New Rules
4 |
5 | Rule ID | Category | Severity | Notes
6 | --------|----------|----------|--------------------
7 | EFP0001 | Design | Error |
8 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/AnalyzerReleases.Unshipped.md:
--------------------------------------------------------------------------------
1 | ### New Rules
2 |
3 | Rule ID | Category | Severity | Notes
4 | --------|----------|----------|--------------------
5 | EFP0002 | Design | Error |
6 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/Diagnostics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.CodeAnalysis;
7 |
8 | namespace EntityFrameworkCore.Projectables.Generator
9 | {
10 | public static class Diagnostics
11 | {
12 | public static readonly DiagnosticDescriptor RequiresExpressionBodyDefinition = new DiagnosticDescriptor(
13 | id: "EFP0001",
14 | title: "Method or property should expose an expression body definition",
15 | messageFormat: "Method or property '{0}' should expose an expression body definition",
16 | category: "Design",
17 | DiagnosticSeverity.Error,
18 | isEnabledByDefault: true);
19 |
20 | public static readonly DiagnosticDescriptor NullConditionalRewriteUnsupported = new DiagnosticDescriptor(
21 | id: "EFP0002",
22 | title: "Method or property is not configured to support null-conditional expressions",
23 | messageFormat: "'{0}' has a null-conditional expression exposed but is not configured to rewrite this (Consider configuring a strategy using the NullConditionalRewriteSupport property on the Projectable attribute)",
24 | category: "Design",
25 | DiagnosticSeverity.Error,
26 | isEnabledByDefault: true);
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/EntityFrameworkCore.Projectables.Generator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | $(NoWarn);NU5128
6 | false
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/MemberDeclarationSyntaxAndCompilationEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.CodeAnalysis;
2 | using Microsoft.CodeAnalysis.CSharp.Syntax;
3 |
4 | namespace EntityFrameworkCore.Projectables.Generator;
5 |
6 | public class MemberDeclarationSyntaxAndCompilationEqualityComparer : IEqualityComparer<(MemberDeclarationSyntax, Compilation)>
7 | {
8 | public bool Equals((MemberDeclarationSyntax, Compilation) x, (MemberDeclarationSyntax, Compilation) y)
9 | {
10 | return GetMemberDeclarationSyntaxAndCompilationName(x.Item1, x.Item2) == GetMemberDeclarationSyntaxAndCompilationName(y.Item1, y.Item2);
11 | }
12 |
13 | public int GetHashCode((MemberDeclarationSyntax, Compilation) obj)
14 | {
15 | return GetMemberDeclarationSyntaxAndCompilationName(obj.Item1, obj.Item2).GetHashCode();
16 | }
17 |
18 | public static string GetMemberDeclarationSyntaxAndCompilationName(MemberDeclarationSyntax memberDeclarationSyntax, Compilation compilation)
19 | {
20 | return $"{compilation.AssemblyName}:{MemberDeclarationSyntaxEqualityComparer.GetMemberDeclarationSyntaxName(memberDeclarationSyntax)}";
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/MemberDeclarationSyntaxEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using Microsoft.CodeAnalysis.CSharp.Syntax;
3 |
4 | namespace EntityFrameworkCore.Projectables.Generator;
5 |
6 | public class MemberDeclarationSyntaxEqualityComparer : IEqualityComparer
7 | {
8 | public bool Equals(MemberDeclarationSyntax x, MemberDeclarationSyntax y)
9 | {
10 | return GetMemberDeclarationSyntaxName(x) == GetMemberDeclarationSyntaxName(y);
11 | }
12 |
13 | public int GetHashCode(MemberDeclarationSyntax obj)
14 | {
15 | return GetMemberDeclarationSyntaxName(obj).GetHashCode();
16 | }
17 |
18 | public static string GetMemberDeclarationSyntaxName(MemberDeclarationSyntax memberDeclaration)
19 | {
20 | var sb = new StringBuilder();
21 |
22 | // Get the member name
23 | if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
24 | {
25 | sb.Append(methodDeclaration.Identifier.Text);
26 | }
27 | else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration)
28 | {
29 | sb.Append(propertyDeclaration.Identifier.Text);
30 | }
31 | else if (memberDeclaration is FieldDeclarationSyntax fieldDeclaration)
32 | {
33 | sb.Append(string.Join(", ", fieldDeclaration.Declaration.Variables.Select(v => v.Identifier.Text)));
34 | }
35 |
36 | // Traverse up the tree to get containing type names
37 | var parent = memberDeclaration.Parent;
38 | while (parent != null)
39 | {
40 | switch (parent)
41 | {
42 | case NamespaceDeclarationSyntax namespaceDeclaration:
43 | sb.Insert(0, namespaceDeclaration.Name + ".");
44 | break;
45 | case ClassDeclarationSyntax classDeclaration:
46 | sb.Insert(0, classDeclaration.Identifier.Text + ".");
47 | break;
48 | case StructDeclarationSyntax structDeclaration:
49 | sb.Insert(0, structDeclaration.Identifier.Text + ".");
50 | break;
51 | case InterfaceDeclarationSyntax interfaceDeclaration:
52 | sb.Insert(0, interfaceDeclaration.Identifier.Text + ".");
53 | break;
54 | case EnumDeclarationSyntax enumDeclaration:
55 | sb.Insert(0, enumDeclaration.Identifier.Text + ".");
56 | break;
57 | }
58 | parent = parent.Parent;
59 | }
60 |
61 | return sb.ToString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/ProjectableDescriptor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.CodeAnalysis;
2 | using Microsoft.CodeAnalysis.CSharp.Syntax;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Collections.Immutable;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace EntityFrameworkCore.Projectables.Generator
11 | {
12 | public class ProjectableDescriptor
13 | {
14 | public IEnumerable? UsingDirectives { get; set; }
15 |
16 | public string? ClassNamespace { get; set; }
17 |
18 | public IEnumerable? NestedInClassNames { get; set; }
19 |
20 | public string? TargetClassNamespace { get; set; }
21 |
22 | public IEnumerable? TargetNestedInClassNames { get; set; }
23 |
24 | public string? ClassName { get; set; }
25 |
26 | public TypeParameterListSyntax? ClassTypeParameterList { get; set; }
27 |
28 | public SyntaxList? ClassConstraintClauses { get; set; }
29 |
30 | public string? MemberName { get; set; }
31 |
32 | public string? ReturnTypeName { get; set; }
33 |
34 | public ParameterListSyntax? ParametersList { get; set; }
35 |
36 | public TypeParameterListSyntax? TypeParameterList { get; set; }
37 |
38 | public SyntaxList? ConstraintClauses { get; set; }
39 |
40 | public ExpressionSyntax? ExpressionBody { get; set; }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables.Generator/VariableReplacementRewriter.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.CodeAnalysis;
2 | using Microsoft.CodeAnalysis.CSharp;
3 | using Microsoft.CodeAnalysis.CSharp.Syntax;
4 | namespace EntityFrameworkCore.Projectables.Generator;
5 |
6 | public class VariableReplacementRewriter : CSharpSyntaxRewriter
7 | {
8 | private readonly string _variableName;
9 | private readonly ExpressionSyntax _replacement;
10 |
11 | public VariableReplacementRewriter(string variableName, ExpressionSyntax replacement)
12 | {
13 | _variableName = variableName;
14 | _replacement = replacement;
15 | }
16 |
17 | public override SyntaxNode? VisitIdentifierName(IdentifierNameSyntax node)
18 | {
19 | if (node.Identifier.ValueText == _variableName)
20 | {
21 | return _replacement;
22 | }
23 |
24 | return base.VisitIdentifierName(node);
25 | }
26 |
27 | public override SyntaxNode? VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
28 | {
29 | if (node.Expression is IdentifierNameSyntax identifier &&
30 | identifier.Identifier.ValueText == _variableName)
31 | {
32 | return SyntaxFactory.MemberAccessExpression(
33 | SyntaxKind.SimpleMemberAccessExpression,
34 | _replacement,
35 | node.Name
36 | );
37 | }
38 |
39 | return base.VisitMemberAccessExpression(node);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/EntityFrameworkCore.Projectables.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | README.md
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Extensions/DbContextOptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | using EntityFrameworkCore.Projectables.Infrastructure;
2 | using EntityFrameworkCore.Projectables.Infrastructure.Internal;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Net;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace Microsoft.EntityFrameworkCore
13 | {
14 | public static class DbContextOptionsExtensions
15 | {
16 | ///
17 | /// Use projectables within the queries. Any call to a Projectable property/method will automatically be translated to the underlying expression tree instead
18 | ///
19 | public static DbContextOptionsBuilder UseProjectables(this DbContextOptionsBuilder optionsBuilder, Action? configure = null)
20 | where TContext : DbContext
21 | => (DbContextOptionsBuilder)UseProjectables((DbContextOptionsBuilder)optionsBuilder, configure);
22 |
23 | ///
24 | /// Use projectables within the queries. Any call to a Projectable property/method will automatically be translated to the underlying expression tree instead
25 | ///
26 | public static DbContextOptionsBuilder UseProjectables(this DbContextOptionsBuilder optionsBuilder, Action? configure = null)
27 | {
28 | var extension = optionsBuilder.Options.FindExtension() ?? new ProjectionOptionsExtension();
29 | ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
30 |
31 | configure?.Invoke(new ProjectableOptionsBuilder(optionsBuilder));
32 |
33 | return optionsBuilder;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Extensions/ExpressionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.Services;
8 |
9 | namespace EntityFrameworkCore.Projectables.Extensions
10 | {
11 | public static class ExpressionExtensions
12 | {
13 | [Obsolete("Use ExpandProjectables instead")]
14 | public static Expression ExpandQuaryables(this Expression expression)
15 | => ExpandProjectables(expression);
16 |
17 | ///
18 | /// Replaces all calls to properties and methods that are marked with the Projectable attribute with their respective expression tree
19 | ///
20 | public static Expression ExpandProjectables(this Expression expression)
21 | => new ProjectableExpressionReplacer(new ProjectionExpressionResolver(), false).Replace(expression);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Extensions/QueryableExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.Services;
7 |
8 | namespace EntityFrameworkCore.Projectables.Extensions
9 | {
10 | public static class QueryableExtensions
11 | {
12 | [Obsolete("Use ExpandProjectables instead")]
13 | public static IQueryable ExpandQuaryables(this IQueryable query)
14 | => ExpandProjectables(query);
15 |
16 | ///
17 | /// Replaces all calls to properties and methods that are marked with the Projectable attribute with their respective expression tree
18 | ///
19 | public static IQueryable ExpandProjectables(this IQueryable query)
20 | => query.Provider.CreateQuery(query.Expression.ExpandProjectables());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/CompatibilityMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EntityFrameworkCore.Projectables.Infrastructure
8 | {
9 | public enum CompatibilityMode
10 | {
11 | ///
12 | /// Projectables are expanded on each individual query invocation.
13 | ///
14 | Full,
15 | ///
16 | /// Projectables are expanded in the query preprocessor and afterwards cached.
17 | /// This yields some performance benefits over native EF with the downside of being incompatible with dynamic parameters.
18 | ///
19 | Limited
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomConventionSetPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Metadata.Conventions;
2 | using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
3 |
4 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
5 |
6 | public class CustomConventionSetPlugin : IConventionSetPlugin
7 | {
8 | public ConventionSet ModifyConventions(ConventionSet conventionSet)
9 | {
10 | conventionSet.ModelFinalizingConventions.Add(new ProjectablesExpandQueryFiltersConvention());
11 |
12 | return conventionSet;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomQueryCompiler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using System.Transactions;
9 | using EntityFrameworkCore.Projectables.Services;
10 | using Microsoft.EntityFrameworkCore;
11 | using Microsoft.EntityFrameworkCore.Diagnostics;
12 | using Microsoft.EntityFrameworkCore.Infrastructure;
13 | using Microsoft.EntityFrameworkCore.Metadata;
14 | using Microsoft.EntityFrameworkCore.Query;
15 | using Microsoft.EntityFrameworkCore.Query.Internal;
16 | using Microsoft.EntityFrameworkCore.Storage;
17 |
18 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal
19 | {
20 | ///
21 | /// Foo
22 | ///
23 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "Needed")]
24 | public sealed class CustomQueryCompiler : QueryCompiler
25 | {
26 | readonly IQueryCompiler _decoratedQueryCompiler;
27 | readonly ProjectableExpressionReplacer _projectableExpressionReplacer;
28 |
29 | public CustomQueryCompiler(IQueryCompiler decoratedQueryCompiler,
30 | IQueryContextFactory queryContextFactory,
31 | ICompiledQueryCache compiledQueryCache,
32 | ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator,
33 | IDatabase database,
34 | IDbContextOptions contextOptions,
35 | IDiagnosticsLogger logger,
36 | ICurrentDbContext currentContext,
37 | IEvaluatableExpressionFilter evaluatableExpressionFilter,
38 | IModel model) : base(queryContextFactory,
39 | compiledQueryCache,
40 | compiledQueryCacheKeyGenerator,
41 | database,
42 | logger,
43 | currentContext,
44 | evaluatableExpressionFilter,
45 | model)
46 | {
47 | _decoratedQueryCompiler = decoratedQueryCompiler;
48 | var trackingByDefault = (contextOptions.FindExtension()?.QueryTrackingBehavior ?? QueryTrackingBehavior.TrackAll) ==
49 | QueryTrackingBehavior.TrackAll;
50 |
51 | _projectableExpressionReplacer = new ProjectableExpressionReplacer(new ProjectionExpressionResolver(), trackingByDefault);
52 | }
53 |
54 | public override Func CreateCompiledAsyncQuery(Expression query)
55 | => _decoratedQueryCompiler.CreateCompiledAsyncQuery(Expand(query));
56 | public override Func CreateCompiledQuery(Expression query)
57 | => _decoratedQueryCompiler.CreateCompiledQuery(Expand(query));
58 | public override TResult Execute(Expression query)
59 | => _decoratedQueryCompiler.Execute(Expand(query));
60 | public override TResult ExecuteAsync(Expression query, CancellationToken cancellationToken)
61 | => _decoratedQueryCompiler.ExecuteAsync(Expand(query), cancellationToken);
62 |
63 | Expression Expand(Expression expression)
64 | => _projectableExpressionReplacer.Replace(expression);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomQueryTranslationPreprocessor.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 | using EntityFrameworkCore.Projectables.Extensions;
3 | using Microsoft.EntityFrameworkCore.Query;
4 |
5 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal
6 | {
7 | public class CustomQueryTranslationPreprocessor : QueryTranslationPreprocessor
8 | {
9 | readonly QueryTranslationPreprocessor _decoratedPreprocessor;
10 |
11 | public CustomQueryTranslationPreprocessor(QueryTranslationPreprocessor decoratedPreprocessor, QueryTranslationPreprocessorDependencies dependencies, QueryCompilationContext queryCompilationContext) : base(dependencies, queryCompilationContext)
12 | {
13 | _decoratedPreprocessor = decoratedPreprocessor;
14 | }
15 |
16 | public override Expression Process(Expression query)
17 | => _decoratedPreprocessor.Process(query.ExpandProjectables());
18 | }
19 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/CustomQueryTranslationPreprocessorFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.Services;
7 | using Microsoft.EntityFrameworkCore.Query;
8 |
9 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal
10 | {
11 | public class CustomQueryTranslationPreprocessorFactory : IQueryTranslationPreprocessorFactory
12 | {
13 | readonly IQueryTranslationPreprocessorFactory _decoratedFactory;
14 | readonly QueryTranslationPreprocessorDependencies _queryTranslationPreprocessorDependencies;
15 |
16 | public CustomQueryTranslationPreprocessorFactory(IQueryTranslationPreprocessorFactory decoratedFactory, QueryTranslationPreprocessorDependencies queryTranslationPreprocessorDependencies)
17 | {
18 | _decoratedFactory = decoratedFactory;
19 | _queryTranslationPreprocessorDependencies = queryTranslationPreprocessorDependencies;
20 | }
21 |
22 | public QueryTranslationPreprocessor Create(QueryCompilationContext queryCompilationContext)
23 | => new CustomQueryTranslationPreprocessor(_decoratedFactory.Create(queryCompilationContext), _queryTranslationPreprocessorDependencies, queryCompilationContext);
24 | }
25 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablePropertiesNotMappedConvention.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
8 | using Microsoft.EntityFrameworkCore.Metadata.Conventions;
9 |
10 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
11 |
12 | public class ProjectablePropertiesNotMappedConvention : IEntityTypeAddedConvention
13 | {
14 | public void ProcessEntityTypeAdded(IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext context)
15 | {
16 | if (entityTypeBuilder.Metadata.ClrType is null)
17 | {
18 | return;
19 | }
20 |
21 | foreach (var property in entityTypeBuilder.Metadata.ClrType.GetRuntimeProperties())
22 | {
23 | if (property.GetCustomAttribute() is not null)
24 | {
25 | entityTypeBuilder.Ignore(property.Name);
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablePropertiesNotMappedConventionPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Metadata.Conventions;
2 | using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
3 |
4 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
5 |
6 | public class ProjectablePropertiesNotMappedConventionPlugin : IConventionSetPlugin
7 | {
8 | public ConventionSet ModifyConventions(ConventionSet conventionSet)
9 | {
10 | conventionSet.EntityTypeAddedConventions.Add(new ProjectablePropertiesNotMappedConvention());
11 | return conventionSet;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/Internal/ProjectablesExpandQueryFiltersConvention.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 | using EntityFrameworkCore.Projectables.Extensions;
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 | using Microsoft.EntityFrameworkCore.Metadata.Conventions;
5 |
6 | namespace EntityFrameworkCore.Projectables.Infrastructure.Internal;
7 |
8 | public class ProjectablesExpandQueryFiltersConvention : IModelFinalizingConvention
9 | {
10 |
11 | ///
12 | public void ProcessModelFinalizing(
13 | IConventionModelBuilder modelBuilder,
14 | IConventionContext context)
15 | {
16 | foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
17 | {
18 | var queryFilter = entityType.GetQueryFilter();
19 | if (queryFilter != null)
20 | {
21 | // Expands query filters
22 | entityType.SetQueryFilter(queryFilter.ExpandProjectables() as LambdaExpression);
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Infrastructure/ProjectableOptionsBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.Infrastructure.Internal;
7 | using Microsoft.EntityFrameworkCore;
8 | using Microsoft.EntityFrameworkCore.Infrastructure;
9 |
10 | namespace EntityFrameworkCore.Projectables.Infrastructure
11 | {
12 | public class ProjectableOptionsBuilder
13 | {
14 | readonly DbContextOptionsBuilder _optionsBuilder;
15 |
16 | public ProjectableOptionsBuilder(DbContextOptionsBuilder optionsBuilder)
17 | {
18 | _optionsBuilder = optionsBuilder ?? throw new ArgumentNullException(nameof(optionsBuilder));
19 | }
20 |
21 | ///
22 | /// Change the default CompatibilityMode
23 | ///
24 | public ProjectableOptionsBuilder CompatibilityMode(CompatibilityMode mode)
25 | => WithOption(x => x.WithCompatibilityMode(mode));
26 |
27 | ///
28 | /// Sets an option by cloning the extension used to store the settings. This ensures the builder
29 | /// does not modify options that are already in use elsewhere.
30 | ///
31 | /// An action to set the option.
32 | /// The same builder instance so that multiple calls can be chained.
33 | protected virtual ProjectableOptionsBuilder WithOption(Func setAction)
34 | {
35 | ((IDbContextOptionsBuilderInfrastructure)_optionsBuilder).AddOrUpdateExtension(
36 | setAction(_optionsBuilder.Options.FindExtension() ?? new ProjectionOptionsExtension()));
37 |
38 | return this;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Services/ExpressionArgumentReplacer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace EntityFrameworkCore.Projectables.Services
9 | {
10 | public sealed class ExpressionArgumentReplacer : ExpressionVisitor
11 | {
12 | public Dictionary ParameterArgumentMapping { get; } = new();
13 |
14 | protected override Expression VisitParameter(ParameterExpression node)
15 | {
16 | if (ParameterArgumentMapping.TryGetValue(node, out var mappedArgument))
17 | {
18 | return mappedArgument;
19 | }
20 |
21 | return base.VisitParameter(node);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Services/IProjectionExpressionResolver.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 | using System.Reflection;
3 |
4 | namespace EntityFrameworkCore.Projectables.Services
5 | {
6 | public interface IProjectionExpressionResolver
7 | {
8 | LambdaExpression FindGeneratedExpression(MemberInfo projectableMemberInfo);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/EntityFrameworkCore.Projectables/Services/ProjectionExpressionClassNameGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EntityFrameworkCore.Projectables.Services
8 | {
9 | public static class ProjectionExpressionClassNameGenerator
10 | {
11 | public const string Namespace = "EntityFrameworkCore.Projectables.Generated";
12 |
13 | public static string GenerateName(string? namespaceName, IEnumerable? nestedInClassNames, string memberName)
14 | {
15 | var stringBuilder = new StringBuilder();
16 |
17 | return GenerateNameImpl(stringBuilder, namespaceName, nestedInClassNames, memberName);
18 | }
19 |
20 | public static string GenerateFullName(string? namespaceName, IEnumerable? nestedInClassNames, string memberName)
21 | {
22 | var stringBuilder = new StringBuilder(Namespace);
23 | stringBuilder.Append('.');
24 |
25 | return GenerateNameImpl(stringBuilder, namespaceName, nestedInClassNames, memberName);
26 | }
27 |
28 | static string GenerateNameImpl(StringBuilder stringBuilder, string? namespaceName, IEnumerable? nestedInClassNames, string memberName)
29 | {
30 | stringBuilder.Append(namespaceName?.Replace('.', '_'));
31 | stringBuilder.Append('_');
32 | var arity = 0;
33 |
34 | if (nestedInClassNames is not null)
35 | {
36 |
37 | foreach (var className in nestedInClassNames)
38 | {
39 | var arityCharacterIndex = className.IndexOf('`');
40 | if (arityCharacterIndex is -1)
41 | {
42 | stringBuilder.Append(className);
43 | }
44 | else
45 | {
46 | #if NETSTANDARD2_0
47 | arity += int.Parse(className.Substring(arityCharacterIndex + 1));
48 | #else
49 | arity += int.Parse(className.AsSpan().Slice(arityCharacterIndex + 1));
50 | #endif
51 | stringBuilder.Append(className, 0, arityCharacterIndex);
52 | }
53 |
54 | stringBuilder.Append('_');
55 | }
56 |
57 | }
58 | stringBuilder.Append(memberName);
59 |
60 | if (arity > 0)
61 | {
62 | stringBuilder.Append('`');
63 | stringBuilder.Append(arity);
64 | }
65 |
66 | return stringBuilder.ToString();
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ChangeTrackerTests.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Threading.Tasks;
3 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
4 | using EntityFrameworkCore.Projectables.Infrastructure;
5 | using Microsoft.EntityFrameworkCore;
6 | using Xunit;
7 |
8 | namespace EntityFrameworkCore.Projectables.FunctionalTests;
9 |
10 | public class ChangeTrackerTests
11 | {
12 | public class SqliteSampleDbContext : DbContext
13 | where TEntity : class
14 | {
15 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
16 | {
17 | optionsBuilder.UseSqlite("Data Source=test.sqlite");
18 | optionsBuilder.UseProjectables();
19 | }
20 |
21 | protected override void OnModelCreating(ModelBuilder modelBuilder)
22 | {
23 | modelBuilder.Entity();
24 | }
25 | }
26 |
27 | public record Entity
28 | {
29 | private static int _nextId = 1;
30 | public const int Computed1DefaultValue = -1;
31 | public int Id { get; set; } = _nextId++;
32 | public string? Name { get; set; }
33 |
34 | [Projectable(UseMemberBody = nameof(InternalComputed1))]
35 | public int Computed1 { get; set; } = Computed1DefaultValue;
36 | private int InternalComputed1 => Id;
37 |
38 | [Projectable]
39 | public int Computed2 => Id * 2;
40 | }
41 |
42 | [Fact]
43 | public async Task CanQueryAndChangeTrackedEntities()
44 | {
45 | using var dbContext = new SqliteSampleDbContext();
46 | await dbContext.Database.EnsureDeletedAsync();
47 | await dbContext.Database.EnsureCreatedAsync();
48 | dbContext.Add(new Entity());
49 | await dbContext.SaveChangesAsync();
50 | dbContext.ChangeTracker.Clear();
51 |
52 | var entity = await dbContext.Set().AsTracking().FirstAsync();
53 | var entityEntry = dbContext.ChangeTracker.Entries().Single();
54 | Assert.Same(entityEntry.Entity, entity);
55 | dbContext.Set().Remove(entity);
56 | await dbContext.SaveChangesAsync();
57 | }
58 |
59 | [Fact]
60 | public async Task CanSaveChanges()
61 | {
62 | using var dbContext = new SqliteSampleDbContext();
63 | await dbContext.Database.EnsureDeletedAsync();
64 | await dbContext.Database.EnsureCreatedAsync();
65 | dbContext.Add(new Entity());
66 | await dbContext.SaveChangesAsync();
67 | dbContext.ChangeTracker.Clear();
68 |
69 | var entity = await dbContext.Set().AsTracking().FirstAsync();
70 | entity.Name = "test";
71 | await dbContext.SaveChangesAsync();
72 | dbContext.ChangeTracker.Clear();
73 | var entity2 = await dbContext.Set().FirstAsync();
74 | Assert.Equal("test", entity2.Name);
75 | }
76 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ArrayOfPrimitivesArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
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 | )
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ArrayOfPrimitivesArguments.verified.txt:
--------------------------------------------------------------------------------
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 | )
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ListOfPrimitivesArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
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 | )
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ListOfPrimitivesArguments.verified.txt:
--------------------------------------------------------------------------------
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 | )
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ParamsOfPrimitivesArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t].[Id]
2 | FROM [TestEntity] AS [t]
3 | WHERE [t].[Id] IN (1, 2, 3)
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.ParamsOfPrimitivesArguments.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t].[Id]
2 | FROM [TestEntity] AS [t]
3 | WHERE [t].[Id] IN (1, 2, 3)
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.SupportsListArguments.verified.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koenbeuk/EntityFrameworkCore.Projectables/552908d6b0923d39808af676ae6d4d3707389cf6/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.SupportsListArguments.verified.txt
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexArgumentsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests
12 | {
13 | [UsesVerify]
14 | public class ComplexArgumentsTests
15 | {
16 | public class TestEntity
17 | {
18 | public int Id { get; set; }
19 |
20 | [Projectable]
21 | public bool IsValid1(List validIds) => validIds.Contains(Id);
22 |
23 | [Projectable]
24 | public bool IsValid2(int[] validIds) => validIds.Contains(Id);
25 |
26 | [Projectable]
27 | public bool IsValid3(params int[] validIds) => validIds.Contains(Id);
28 | }
29 |
30 | [Fact]
31 | public Task ListOfPrimitivesArguments()
32 | {
33 | using var dbContext = new SampleDbContext();
34 |
35 | var validList = new List() { 1, 2, 3 };
36 |
37 | var query = dbContext.Set()
38 | .Where(x => x.IsValid1(validList));
39 |
40 | return Verifier.Verify(query.ToQueryString());
41 | }
42 |
43 | [Fact]
44 | public Task ArrayOfPrimitivesArguments()
45 | {
46 | using var dbContext = new SampleDbContext();
47 |
48 | var validArray = new[] { 1, 2, 3 };
49 |
50 | var query = dbContext.Set()
51 | .Where(x => x.IsValid2(validArray));
52 |
53 | return Verifier.Verify(query.ToQueryString());
54 | }
55 |
56 |
57 | [Fact]
58 | public Task ParamsOfPrimitivesArguments()
59 | {
60 | using var dbContext = new SampleDbContext();
61 |
62 | var query = dbContext.Set()
63 | .Where(x => x.IsValid3(1, 2, 3));
64 |
65 | return Verifier.Verify(query.ToQueryString());
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverCollectionNavigationProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
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]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverCollectionNavigationProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t0].[RecordDate]
2 | FROM [User] AS [u]
3 | INNER JOIN (
4 | SELECT [t].[RecordDate], [t].[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 [t]
9 | WHERE [t].[row] <= 2
10 | ) AS [t0] ON [u].[Id] = [t0].[UserId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverMethodTakingDbContext.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [o1].[Id], [o1].[RecordDate], [o1].[UserId]
2 | FROM [User] AS [u]
3 | LEFT JOIN (
4 | SELECT [o0].[Id], [o0].[RecordDate], [o0].[UserId]
5 | FROM (
6 | SELECT [o].[Id], [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] <= 1
10 | ) AS [o1] ON [u].[Id] = [o1].[UserId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverMethodTakingDbContext.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t0].[Id], [t0].[RecordDate], [t0].[UserId]
2 | FROM [User] AS [u]
3 | LEFT JOIN (
4 | SELECT [t].[Id], [t].[RecordDate], [t].[UserId]
5 | FROM (
6 | SELECT [o].[Id], [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 [t]
9 | WHERE [t].[row] <= 1
10 | ) AS [t0] ON [u].[Id] = [t0].[UserId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverNavigationProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT (
2 | SELECT TOP(1) [o].[RecordDate]
3 | FROM [Order] AS [o]
4 | WHERE [u].[Id] = [o].[UserId]
5 | ORDER BY [o].[RecordDate] DESC)
6 | FROM [User] AS [u]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectOverNavigationProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT (
2 | SELECT TOP(1) [o].[RecordDate]
3 | FROM [Order] AS [o]
4 | WHERE [u].[Id] = [o].[UserId]
5 | ORDER BY [o].[RecordDate] DESC)
6 | FROM [User] AS [u]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ComplexModelTests.ProjectQueryFilters.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t0].[RecordDate]
2 | FROM [User] AS [u]
3 | INNER JOIN (
4 | SELECT [t].[RecordDate], [t].[UserId]
5 | FROM (
6 | SELECT [o0].[RecordDate], [o0].[UserId], ROW_NUMBER() OVER(PARTITION BY [o0].[UserId] ORDER BY [o0].[RecordDate] DESC) AS [row]
7 | FROM [Order] AS [o0]
8 | ) AS [t]
9 | WHERE [t].[row] <= 2
10 | ) AS [t0] ON [u].[Id] = [t0].[UserId]
11 | WHERE (
12 | SELECT TOP(1) [o].[Id]
13 | FROM [Order] AS [o]
14 | WHERE [u].[Id] = [o].[UserId]
15 | ORDER BY [o].[RecordDate] DESC) > 100
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/DefaultValueTests.ExplicitDefaultValueIsSupported.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/DefaultValueTests.ExplicitDefaultValueIsSupported.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/DefaultValueTests.cs:
--------------------------------------------------------------------------------
1 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
2 | using Microsoft.EntityFrameworkCore;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using VerifyXunit;
6 | using Xunit;
7 |
8 | namespace EntityFrameworkCore.Projectables.FunctionalTests
9 | {
10 | [UsesVerify]
11 | public class DefaultValueTests
12 | {
13 | public record Entity
14 | {
15 | public int Id { get; set; }
16 |
17 | [Projectable]
18 | public int NextId(int skip = 1) => Id + skip;
19 | }
20 |
21 | [Fact]
22 | public Task ExplicitDefaultValueIsSupported()
23 | {
24 | using var dbContext = new SampleDbContext();
25 |
26 | var query = dbContext.Set()
27 | .Select(x => x.NextId(2));
28 |
29 | return Verifier.Verify(query.ToQueryString());
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/EntityFrameworkCore.Projectables.FunctionalTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0
5 | false
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | all
21 | runtime; build; native; contentfiles; analyzers; buildtransitive
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/EnumerableProjectableTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 |
9 | namespace EntityFrameworkCore.Projectables.FunctionalTests
10 | {
11 | public class EnumerableProjectableTests
12 | {
13 | public class Product
14 | {
15 | public int Id { get; set; }
16 |
17 | public List Prices { get; } = [];
18 |
19 | [Projectable]
20 | public IEnumerable CheapPrices => Prices.Where(x => x.Price < 10D);
21 | }
22 |
23 | public class ProductPrice
24 | {
25 | public int Id { get; set; }
26 |
27 | public double Price { get; set; }
28 | }
29 |
30 | [Fact]
31 | public void ProjectableProperty_IsIgnoredFromMapping()
32 | {
33 | var dbContext = new SampleDbContext();
34 | var productPriceType = dbContext.Model.GetEntityTypes().Single(x => x.ClrType == typeof(ProductPrice));
35 |
36 | // Assert 3 properties: Id, Price, ProductId (synthetic)
37 | Assert.Equal(3, productPriceType.GetProperties().Count());
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/Entity.cs:
--------------------------------------------------------------------------------
1 | namespace EntityFrameworkCore.Projectables.FunctionalTests.ExtensionMethods
2 | {
3 | public class Entity
4 | {
5 | public int Id { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/EntityExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using Microsoft.EntityFrameworkCore;
3 |
4 | namespace EntityFrameworkCore.Projectables.FunctionalTests.ExtensionMethods
5 | {
6 | public static class EntityExtensions
7 | {
8 | [Projectable]
9 | public static int Squared(this int i) => i * i;
10 |
11 | [Projectable]
12 | public static int Foo(this Entity entity) => entity.Id + 1;
13 |
14 | [Projectable]
15 | public static int Foo2(this Entity entity) => entity.Foo() + 1;
16 |
17 | [Projectable]
18 | public static Entity? LeadingEntity(this Entity entity, DbContext dbContext)
19 | => dbContext.Set().Where(y => y.Id > entity.Id).FirstOrDefault();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.ExtensionMethodAcceptingDbContext.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e1].[Id]
2 | FROM [Entity] AS [e]
3 | OUTER APPLY (
4 | SELECT TOP(1) [e0].[Id]
5 | FROM [Entity] AS [e0]
6 | WHERE [e0].[Id] > [e].[Id]
7 | ) AS [e1]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.ExtensionMethodAcceptingDbContext.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t].[Id]
2 | FROM [Entity] AS [e]
3 | OUTER APPLY (
4 | SELECT TOP(1) [e0].[Id]
5 | FROM [Entity] AS [e0]
6 | WHERE [e0].[Id] > [e].[Id]
7 | ) AS [t]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.ExtensionOnPrimitive.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.ExtensionOnPrimitive.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1 + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1 + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
9 | using ScenarioTests;
10 | using VerifyXunit;
11 | using Xunit;
12 |
13 | namespace EntityFrameworkCore.Projectables.FunctionalTests.ExtensionMethods
14 | {
15 |
16 | [UsesVerify]
17 | public class ExtensionMethodTests
18 | {
19 | [Fact]
20 | public Task ExtensionOnPrimitive()
21 | {
22 | using var dbContext = new SampleDbContext();
23 |
24 | var query = dbContext.Set()
25 | .Select(x => x.Id.Squared());
26 |
27 | return Verifier.Verify(query.ToQueryString());
28 | }
29 |
30 | [Fact]
31 | public Task SelectProjectableExtensionMethod()
32 | {
33 | using var dbContext = new SampleDbContext();
34 |
35 | var query = dbContext.Set()
36 | .Select(x => x.Foo());
37 |
38 | return Verifier.Verify(query.ToQueryString());
39 | }
40 |
41 | [Fact]
42 | public Task SelectProjectableExtensionMethod2()
43 | {
44 | using var dbContext = new SampleDbContext();
45 |
46 | var query = dbContext.Set()
47 | .Select(x => x.Foo2());
48 |
49 | return Verifier.Verify(query.ToQueryString());
50 | }
51 |
52 | [Fact]
53 | public Task ExtensionMethodAcceptingDbContext()
54 | {
55 | using var dbContext = new SampleDbContext(Infrastructure.CompatibilityMode.Full);
56 |
57 | var sampleQuery = dbContext.Set()
58 | .Select(x => dbContext.Set().Where(y => y.Id > x.Id).FirstOrDefault());
59 |
60 | var query = dbContext.Set()
61 | .Select(x => x.LeadingEntity(dbContext));
62 |
63 | return Verifier.Verify(query.ToQueryString());
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/Entity.cs:
--------------------------------------------------------------------------------
1 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
2 | {
3 | public record Entity : IEntity
4 | {
5 | public int Id { get; set; }
6 | public string? Name { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/EntityExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
4 | {
5 | public static class EntityExtensions
6 | {
7 | [Projectable]
8 | public static TEntity? DefaultIfIdIsNegative(this TEntity entity) where TEntity : IEntity
9 | => entity.Id >= 0 ? entity : default;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericEntityTests.HasMatchingStringKeyConversion_GetsTranslated.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__key_0 varchar(11) = 'x';
2 |
3 | SELECT [c].[Id]
4 | FROM [ConcreteEntity] AS [c]
5 | WHERE CONVERT(varchar(11), [c].[Id]) = @__key_0
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericEntityTests.HasMatchingStringKeyConversion_GetsTranslated.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__key_0 nvarchar(4000) = N'x';
2 |
3 | SELECT [c].[Id]
4 | FROM [ConcreteEntity] AS [c]
5 | WHERE CONVERT(varchar(11), [c].[Id]) = @__key_0
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericEntityTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
12 | {
13 | [UsesVerify]
14 | public class GenericEntityTests
15 | {
16 | public abstract class BaseEntity
17 | where TSelf : BaseEntity
18 | {
19 | public TKey Id { get; set; } = default!;
20 |
21 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Ignore)]
22 | public bool HasMatchingStringKeyConversion(string key)
23 | => Id?.ToString() == key;
24 | }
25 |
26 | public class ConcreteEntity : BaseEntity
27 | {
28 |
29 | }
30 |
31 | [Fact]
32 | public Task HasMatchingStringKeyConversion_GetsTranslated()
33 | {
34 | using var context = new SampleDbContext();
35 | var key = "x";
36 | var query = context.Set()
37 | .Where(x => x.HasMatchingStringKeyConversion(key))
38 | .Select(x => x.Id);
39 |
40 | return Verifier.Verify(query.ToQueryString());
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericExtensionMethodTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
12 | {
13 | [UsesVerify]
14 | public class GenericFunctionTests
15 | {
16 | [Fact]
17 | public Task DefaultIfIdIsNegative()
18 | {
19 | using var context = new SampleDbContext();
20 | var query = context.Set()
21 | .Select(x => x.DefaultIfIdIsNegative());
22 |
23 | return Verifier.Verify(query.ToQueryString());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericFunctionTests.DefaultIfIdIsNegative.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CASE
2 | WHEN [e].[Id] >= 0 THEN CAST(1 AS bit)
3 | ELSE CAST(0 AS bit)
4 | END, [e].[Id], [e].[Name]
5 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericFunctionTests.DefaultIfIdIsNegative.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CASE
2 | WHEN [e].[Id] >= 0 THEN CAST(1 AS bit)
3 | ELSE CAST(0 AS bit)
4 | END, [e].[Id], [e].[Name]
5 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/GenericFunctionTests.QueryOrderedByDefault.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | ORDER BY [e].[Id]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/IEntity.cs:
--------------------------------------------------------------------------------
1 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
2 | {
3 | public interface IEntity
4 | {
5 | int Id { get; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/MultipleGenericsTests.TestMultipleArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(1 AS bit), [e].[Id], [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/MultipleGenericsTests.TestMultipleArguments.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(1 AS bit), [e].[Id], [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Generics/MultipleGenericsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Generics
12 | {
13 | [UsesVerify]
14 | public class MultipleGenericsTests
15 | {
16 | [Projectable]
17 | public static object? Coalesce(T1? t1, T2 t2)
18 | => t1 != null ? t1 : t2;
19 |
20 | [Fact]
21 | public Task TestMultipleArguments()
22 | {
23 | using var context = new SampleDbContext();
24 |
25 | var query = context.Set()
26 | .Select(x => Coalesce(x.Id, x.Name));
27 |
28 | return Verifier.Verify(query.ToQueryString());
29 | }
30 |
31 | [Fact]
32 | public void MultipleInvocations()
33 | {
34 | using var context = new SampleDbContext(Infrastructure.CompatibilityMode.Full);
35 |
36 | var query1 = context.Set()
37 | .Select(x => Coalesce(x.Id, x.Name))
38 | .ToQueryString();
39 |
40 | var query2 = context.Set()
41 | .Select(x => Coalesce(x.Name, x.Id))
42 | .ToQueryString();
43 |
44 | Assert.NotEqual(query1, query2);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Helpers/SampleDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Common;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.Extensions;
8 | using EntityFrameworkCore.Projectables.Infrastructure;
9 | using Microsoft.EntityFrameworkCore;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Helpers
12 | {
13 | public class SampleDbContext : DbContext
14 | where TEntity : class
15 | {
16 | readonly CompatibilityMode _compatibilityMode;
17 | readonly QueryTrackingBehavior _queryTrackingBehavior;
18 |
19 | public SampleDbContext(CompatibilityMode compatibilityMode = CompatibilityMode.Full, QueryTrackingBehavior queryTrackingBehavior = QueryTrackingBehavior.TrackAll)
20 | {
21 | _compatibilityMode = compatibilityMode;
22 | _queryTrackingBehavior = queryTrackingBehavior;
23 | }
24 |
25 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
26 | {
27 | optionsBuilder.UseSqlServer("Server=(localdb)\\v11.0;Integrated Security=true"); // Fake connection string as we're actually never connecting
28 | optionsBuilder.UseProjectables(options => {
29 | options.CompatibilityMode(_compatibilityMode); // Needed by our ComplexModelTests
30 | });
31 | optionsBuilder.UseQueryTrackingBehavior(_queryTrackingBehavior);
32 | }
33 |
34 | protected override void OnModelCreating(ModelBuilder modelBuilder)
35 | {
36 | modelBuilder.Entity();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/Helpers/SampleUserWithGlobalQueryFilterDbContext.cs:
--------------------------------------------------------------------------------
1 | using EntityFrameworkCore.Projectables.Infrastructure;
2 | using Microsoft.EntityFrameworkCore;
3 |
4 | namespace EntityFrameworkCore.Projectables.FunctionalTests.Helpers
5 | {
6 | public class SampleUserWithGlobalQueryFilterDbContext : SampleDbContext
7 | {
8 | public SampleUserWithGlobalQueryFilterDbContext(CompatibilityMode compatibilityMode = CompatibilityMode.Full) : base(compatibilityMode)
9 | {
10 | }
11 |
12 | protected override void OnModelCreating(ModelBuilder modelBuilder)
13 | {
14 | base.OnModelCreating(modelBuilder);
15 |
16 | modelBuilder.Entity(b => {
17 | b.HasQueryFilter(u => u.LastOrder.Id > 100);
18 | });
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedMembersTests.ProjectOverMethodTakingDbContext.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST([c].[Age] AS float) / [c].[AverageLifespan] AS [LifeProgression], CAST([c].[MentalAge] AS float) / [c].[AverageLifespan] AS [MentalLifeProgression]
2 | FROM [Cat] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedMembersTests.ProjectOverMethodTakingDbContext.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST([c].[Age] AS float) / [c].[AverageLifespan] AS [LifeProgression], CAST([c].[MentalAge] AS float) / [c].[AverageLifespan] AS [MentalLifeProgression]
2 | FROM [Cat] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedMembersTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests
12 | {
13 | [UsesVerify]
14 | public class InheritedMembersTests
15 | {
16 | public abstract class Animal
17 | {
18 | public int Id { get; set; }
19 | public double AverageLifespan { get; set; }
20 | public int Age { get; set; }
21 |
22 | [Projectable]
23 | public double LifeProgression
24 | => Age / AverageLifespan;
25 | }
26 |
27 | public class Cat : Animal
28 | {
29 | public int MentalAge { get; set; }
30 |
31 | [Projectable]
32 | public double MentalLifeProgression
33 | => MentalAge / AverageLifespan;
34 | }
35 |
36 |
37 | [Fact]
38 | public Task ProjectOverMethodTakingDbContext()
39 | {
40 | using var dbContext = new SampleDbContext();
41 |
42 | var query = dbContext.Set()
43 | .Select(x => new { x.LifeProgression, x.MentalLifeProgression });
44 |
45 | return Verifier.Verify(query.ToQueryString());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverExtensionMethod.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 4
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverExtensionMethod.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 4
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverImplementedMethod.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverImplementedMethod.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverImplementedProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverImplementedProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverInheritedMethodImplementation.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [MoreConcrete] AS [m]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverInheritedMethodImplementation.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [MoreConcrete] AS [m]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverInheritedPropertyImplementation.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [MoreConcrete] AS [m]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverInheritedPropertyImplementation.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [MoreConcrete] AS [m]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverOverriddenMethodImplementation.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverOverriddenMethodImplementation.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverOverriddenPropertyImplementation.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverOverriddenPropertyImplementation.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 2
2 | FROM [Concrete] AS [c]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverProvider.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [c].[Id]
2 | FROM [BaseProvider] AS [b]
3 | INNER JOIN [Concrete] AS [c] ON [b].[Id] = [c].[BaseProviderId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/InheritedModelTests.ProjectOverProvider.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [c].[Id]
2 | FROM [BaseProvider] AS [b]
3 | INNER JOIN [Concrete] AS [c] ON [b].[Id] = [c].[BaseProviderId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/MethodGroupTests.ProjectOverMethodGroup.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e0].[Id] + 1, [e0].[Id]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN [Entity] AS [e0] ON [e].[Id] = [e0].[EntityId]
4 | ORDER BY [e].[Id]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/MethodGroupTests.ProjectOverMethodGroup.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e0].[Id] + 1, [e0].[Id]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN [Entity] AS [e0] ON [e].[Id] = [e0].[EntityId]
4 | ORDER BY [e].[Id]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/MethodGroupTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
5 | using Microsoft.EntityFrameworkCore;
6 | using VerifyXunit;
7 | using Xunit;
8 |
9 | namespace EntityFrameworkCore.Projectables.FunctionalTests;
10 |
11 | [UsesVerify]
12 | public class MethodGroupTests
13 | {
14 | public record Entity
15 | {
16 | public int Id { get; set; }
17 |
18 | public List? RelatedEntities { get; set; }
19 | }
20 |
21 | [Projectable]
22 | public static int NextId(Entity entity) => entity.Id + 1;
23 |
24 | [Fact]
25 | public Task ProjectOverMethodGroup()
26 | {
27 | using var dbContext = new SampleDbContext();
28 |
29 | var query = dbContext.Set()
30 | .Select(x => new { NextIds = x.RelatedEntities!.Select(NextId) });
31 |
32 | return Verifier.Verify(query.ToQueryString());
33 | }
34 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | namespace EntityFrameworkCore.Projectables.FunctionalTests
4 | {
5 | public static class ModuleInitializer
6 | {
7 | [ModuleInitializer]
8 | public static void Initialize()
9 | {
10 | #if !NET8_0
11 | VerifierSettings.UniqueForTargetFrameworkAndVersion();
12 | #endif
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NameSyntaxTests.QualifiedNameSyntaxTest.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 7
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NameSyntaxTests.QualifiedNameSyntaxTest.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 7
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NameSyntaxTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
5 | using Microsoft.EntityFrameworkCore;
6 | using VerifyXunit;
7 | using Xunit;
8 |
9 | namespace EntityFrameworkCore.Projectables.FunctionalTests
10 | {
11 | public class Local
12 | {
13 | [Flags]
14 | public enum SampleEnum
15 | {
16 | One = 0b001,
17 | Two = 0b010,
18 | Four = 0b100,
19 | }
20 | }
21 |
22 | [UsesVerify]
23 | public class NameSyntaxTests
24 | {
25 | public class Entity
26 | {
27 | public int Id { get; set; }
28 |
29 | [Projectable]
30 | public Local.SampleEnum? Test => Local.SampleEnum.One | Local.SampleEnum.Two | Local.SampleEnum.Four;
31 | }
32 |
33 | [Fact]
34 | public Task QualifiedNameSyntaxTest()
35 | {
36 | using var dbContext = new SampleDbContext();
37 |
38 | var query = dbContext.Set()
39 | .Select(x => x.Test);
40 |
41 | return Verifier.Verify(query.ToQueryString());
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/Entity.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace EntityFrameworkCore.Projectables.FunctionalTests.NullConditionals
4 | {
5 | public record Entity
6 | {
7 | public int Id { get; set; }
8 | public string? Name { get; set; }
9 | public List? RelatedEntities { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/EntityExtensions.cs:
--------------------------------------------------------------------------------
1 | #nullable disable
2 |
3 | namespace EntityFrameworkCore.Projectables.FunctionalTests.NullConditionals
4 | {
5 | public static class EntityExtensions
6 | {
7 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Ignore)]
8 | public static string GetNameIgnoreNulls(this Entity entity)
9 | => entity?.Name;
10 |
11 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Ignore)]
12 | public static int? GetNameLengthIgnoreNulls(this Entity entity)
13 | => entity.GetNameIgnoreNulls()?.Length;
14 |
15 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Ignore)]
16 | public static Entity GetFirstRelatedIgnoreNulls(this Entity entity)
17 | => entity?.RelatedEntities?[0];
18 |
19 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Rewrite)]
20 | public static string GetNameRewriteNulls(this Entity entity)
21 | => entity?.Name;
22 |
23 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Rewrite)]
24 | public static int? GetNameLengthRewriteNulls(this Entity entity)
25 | => entity.GetNameIgnoreNulls()?.Length;
26 |
27 | [Projectable(NullConditionalRewriteSupport = NullConditionalRewriteSupport.Rewrite)]
28 | public static Entity GetFirstRelatedRewriteNulls(this Entity entity)
29 | => entity?.RelatedEntities?[0];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.ComplexMemberExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(LEN([e].[Name]) AS int)
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.ComplexMemberExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(LEN([e].[Name]) AS int)
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.RelationalExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e2].[Id], [e2].[EntityId], [e2].[Name]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN (
4 | SELECT [e1].[Id], [e1].[EntityId], [e1].[Name]
5 | FROM (
6 | SELECT [e0].[Id], [e0].[EntityId], [e0].[Name], ROW_NUMBER() OVER(PARTITION BY [e0].[EntityId] ORDER BY [e0].[Id]) AS [row]
7 | FROM [Entity] AS [e0]
8 | ) AS [e1]
9 | WHERE 0 < [e1].[row] AND [e1].[row] <= 1
10 | ) AS [e2] ON [e].[Id] = [e2].[EntityId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.RelationalExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t0].[Id], [t0].[EntityId], [t0].[Name]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN (
4 | SELECT [t].[Id], [t].[EntityId], [t].[Name]
5 | FROM (
6 | SELECT [e0].[Id], [e0].[EntityId], [e0].[Name], ROW_NUMBER() OVER(PARTITION BY [e0].[EntityId] ORDER BY [e0].[Id]) AS [row]
7 | FROM [Entity] AS [e0]
8 | ) AS [t]
9 | WHERE 0 < [t].[row] AND [t].[row] <= 1
10 | ) AS [t0] ON [e].[Id] = [t0].[EntityId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.SimpleMemberExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.SimpleMemberExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/IngoreNullConditionalRewriteTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
6 | using Microsoft.EntityFrameworkCore;
7 | using VerifyXunit;
8 | using Xunit;
9 |
10 | namespace EntityFrameworkCore.Projectables.FunctionalTests.NullConditionals
11 | {
12 | [UsesVerify]
13 | public class IngoreNullConditionalRewriteTests
14 | {
15 | [Fact]
16 | public Task SimpleMemberExpression()
17 | {
18 | using var dbContext = new SampleDbContext();
19 |
20 | var query = dbContext.Set()
21 | .Select(x => x.GetNameIgnoreNulls());
22 |
23 | return Verifier.Verify(query.ToQueryString());
24 | }
25 |
26 | [Fact]
27 | public Task ComplexMemberExpression()
28 | {
29 | using var dbContext = new SampleDbContext();
30 |
31 | var query = dbContext.Set()
32 | .Select(x => x.GetNameLengthIgnoreNulls());
33 |
34 | return Verifier.Verify(query.ToQueryString());
35 | }
36 |
37 | [Fact]
38 | public Task RelationalExpression()
39 | {
40 | using var dbContext = new SampleDbContext();
41 |
42 | var query = dbContext.Set()
43 | .Select(x => x.GetFirstRelatedIgnoreNulls());
44 |
45 | return Verifier.Verify(query.ToQueryString());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.ComplexMemberExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(LEN([e].[Name]) AS int)
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.ComplexMemberExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(LEN([e].[Name]) AS int)
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.RelationalExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(1 AS bit), [e].[Id], [e0].[Id], [e0].[EntityId], [e0].[Name], [e3].[Id], [e3].[EntityId], [e3].[Name]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN [Entity] AS [e0] ON [e].[Id] = [e0].[EntityId]
4 | LEFT JOIN (
5 | SELECT [e2].[Id], [e2].[EntityId], [e2].[Name]
6 | FROM (
7 | SELECT [e1].[Id], [e1].[EntityId], [e1].[Name], ROW_NUMBER() OVER(PARTITION BY [e1].[EntityId] ORDER BY [e1].[Id]) AS [row]
8 | FROM [Entity] AS [e1]
9 | ) AS [e2]
10 | WHERE 0 < [e2].[row] AND [e2].[row] <= 1
11 | ) AS [e3] ON [e].[Id] = [e3].[EntityId]
12 | ORDER BY [e].[Id]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.RelationalExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT CAST(1 AS bit), [e].[Id], [e0].[Id], [e0].[EntityId], [e0].[Name], [t0].[Id], [t0].[EntityId], [t0].[Name]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN [Entity] AS [e0] ON [e].[Id] = [e0].[EntityId]
4 | LEFT JOIN (
5 | SELECT [t].[Id], [t].[EntityId], [t].[Name]
6 | FROM (
7 | SELECT [e1].[Id], [e1].[EntityId], [e1].[Name], ROW_NUMBER() OVER(PARTITION BY [e1].[EntityId] ORDER BY [e1].[Id]) AS [row]
8 | FROM [Entity] AS [e1]
9 | ) AS [t]
10 | WHERE 0 < [t].[row] AND [t].[row] <= 1
11 | ) AS [t0] ON [e].[Id] = [t0].[EntityId]
12 | ORDER BY [e].[Id]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.SimpleMemberExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.SimpleMemberExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Name]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/NullConditionals/RewriteNullConditionalRewriteTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
6 | using Microsoft.EntityFrameworkCore;
7 | using VerifyXunit;
8 | using Xunit;
9 |
10 | namespace EntityFrameworkCore.Projectables.FunctionalTests.NullConditionals
11 | {
12 | [UsesVerify]
13 | public class RewriteNullConditionalRewriteTests
14 | {
15 | [Fact]
16 | public Task SimpleMemberExpression()
17 | {
18 | using var dbContext = new SampleDbContext();
19 |
20 | var query = dbContext.Set()
21 | .Select(x => x.GetNameRewriteNulls());
22 |
23 | return Verifier.Verify(query.ToQueryString());
24 | }
25 |
26 | [Fact]
27 | public Task ComplexMemberExpression()
28 | {
29 | using var dbContext = new SampleDbContext();
30 |
31 | var query = dbContext.Set()
32 | .Select(x => x.GetNameLengthRewriteNulls());
33 |
34 | return Verifier.Verify(query.ToQueryString());
35 | }
36 |
37 | [Fact]
38 | public Task RelationalExpression()
39 | {
40 | using var dbContext = new SampleDbContext();
41 |
42 | var query = dbContext.Set()
43 | .Select(x => x.GetFirstRelatedRewriteNulls());
44 |
45 | return Verifier.Verify(query.ToQueryString());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/PrivateProjectables.Issue63Repro.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/PrivateProjectables.Issue63Repro.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/PrivateProjectables.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests
12 | {
13 | [UsesVerify]
14 | public class PrivateProjectables
15 | {
16 | public record Entity
17 | {
18 | public int Id { get; set; }
19 | }
20 |
21 | bool IsAdmin => true;
22 |
23 | [Fact]
24 | public Task Issue63Repro()
25 | {
26 | using var dbContext = new SampleDbContext();
27 |
28 | var query = dbContext.Set()
29 | .Where(product => IsAdmin || product.Id == 1);
30 |
31 | return Verifier.Verify(query.ToQueryString());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.AsNoTrackingQueryRootExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Id] * 5
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.AsNoTrackingQueryRootExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Id] * 5
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.AsTrackingQueryRootExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.AsTrackingQueryRootExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.DontUseMemberPropertyQueryRootExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.DontUseMemberPropertyQueryRootExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.EntityRootSubqueryExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], (
2 | SELECT COUNT(*)
3 | FROM [Entity] AS [e0]
4 | WHERE [e0].[Id] * 5 = 5) AS [TotalCount]
5 | FROM [Entity] AS [e]
6 | WHERE [e].[Id] * 5 = 5
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.EntityRootSubqueryExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], (
2 | SELECT COUNT(*)
3 | FROM [Entity] AS [e0]
4 | WHERE [e0].[Id] * 5 = 5) AS [TotalCount]
5 | FROM [Entity] AS [e]
6 | WHERE [e].[Id] * 5 = 5
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.UseMemberPropertyQueryRootExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Id] * 5
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.UseMemberPropertyQueryRootExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Id] * 5
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/QueryRootTests.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations.Schema;
2 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
3 | using Microsoft.EntityFrameworkCore;
4 |
5 | namespace EntityFrameworkCore.Projectables.FunctionalTests
6 | {
7 | [UsesVerify]
8 | public class QueryRootTests
9 | {
10 | public record Entity
11 | {
12 | public int Id { get; set; }
13 |
14 | [Projectable(UseMemberBody = nameof(Computed2))]
15 | public int Computed1 => Id;
16 |
17 | private int Computed2 => Id * 2;
18 |
19 | [Projectable(UseMemberBody = nameof(_ComputedWithBaking))]
20 | [NotMapped]
21 | public int ComputedWithBacking { get; set; }
22 |
23 | private int _ComputedWithBaking => Id * 5;
24 | }
25 |
26 | [Fact]
27 | public Task UseMemberPropertyQueryRootExpression()
28 | {
29 | using var dbContext = new SampleDbContext(queryTrackingBehavior: QueryTrackingBehavior.NoTracking);
30 |
31 | var query = dbContext.Set();
32 |
33 | return Verifier.Verify(query.ToQueryString());
34 | }
35 |
36 | [Fact]
37 | public Task DontUseMemberPropertyQueryRootExpression()
38 | {
39 | using var dbContext = new SampleDbContext(queryTrackingBehavior: QueryTrackingBehavior.TrackAll);
40 |
41 | var query = dbContext.Set();
42 |
43 | return Verifier.Verify(query.ToQueryString());
44 | }
45 |
46 |
47 | [Fact]
48 | public Task EntityRootSubqueryExpression()
49 | {
50 | using var dbContext = new SampleDbContext();
51 |
52 | var original = dbContext.Set()
53 | .Where(e => e.ComputedWithBacking == 5);
54 |
55 | var query = original
56 | .Select(e => new { Item = e, TotalCount = original.Count() });
57 |
58 | return Verifier.Verify(query.ToQueryString());
59 | }
60 |
61 | [Fact]
62 | public Task AsTrackingQueryRootExpression()
63 | {
64 | using var dbContext = new SampleDbContext(queryTrackingBehavior: QueryTrackingBehavior.NoTracking);
65 |
66 | var query = dbContext.Set().AsTracking();
67 |
68 | return Verifier.Verify(query.ToQueryString());
69 | }
70 |
71 | [Fact]
72 | public Task AsNoTrackingQueryRootExpression()
73 | {
74 | using var dbContext = new SampleDbContext(queryTrackingBehavior: QueryTrackingBehavior.TrackAll);
75 |
76 | var query = dbContext.Set().AsNoTracking();
77 |
78 | return Verifier.Verify(query.ToQueryString());
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] + 1 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] + 1 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.PassInReferenceArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.PassInReferenceArguments.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.PassInVariableArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__argument_0 int = 1;
2 |
3 | SELECT [e].[Id] + @__argument_0
4 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.PassInVariableArguments.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__argument_0 int = 1;
2 |
3 | SELECT [e].[Id] + @__argument_0
4 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + 1
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullComplexFunctionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 | using EntityFrameworkCore.Projectables.Services;
9 | using Microsoft.EntityFrameworkCore;
10 | using ScenarioTests;
11 | using VerifyXunit;
12 | using Xunit;
13 |
14 | namespace EntityFrameworkCore.Projectables.FunctionalTests
15 | {
16 | [UsesVerify]
17 | public class StatefullComplexFunctionTests
18 | {
19 | public record Entity
20 | {
21 | public int Id { get; set; }
22 |
23 | [Projectable]
24 | public int Computed(int argument) => Id + argument;
25 | }
26 |
27 |
28 | [Fact]
29 | public Task FilterOnProjectableProperty()
30 | {
31 | using var dbContext = new SampleDbContext();
32 |
33 | var query = dbContext.Set()
34 | .Where(x => x.Computed(1) == 2);
35 |
36 | return Verifier.Verify(query.ToQueryString());
37 | }
38 |
39 | [Fact]
40 | public Task SelectProjectableProperty()
41 | {
42 | using var dbContext = new SampleDbContext();
43 |
44 | var query = dbContext.Set()
45 | .Select(x => x.Computed(1));
46 |
47 | return Verifier.Verify(query.ToQueryString());
48 | }
49 |
50 |
51 | [Fact]
52 | public Task PassInVariableArguments()
53 | {
54 | using var dbContext = new SampleDbContext();
55 |
56 | var argument = 1;
57 | var query = dbContext.Set()
58 | .Select(x => x.Computed(argument));
59 |
60 | return Verifier.Verify(query.ToQueryString());
61 | }
62 |
63 | [Fact]
64 | public Task PassInReferenceArguments()
65 | {
66 | using var dbContext = new SampleDbContext();
67 |
68 | var query = dbContext.Set()
69 | .Select(x => x.Computed(x.Id));
70 |
71 | return Verifier.Verify(query.ToQueryString());
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.CombineSelectProjectableProperties.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.CombineSelectProjectableProperties.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.FilterOnComplexProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] * 2 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.FilterOnComplexProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] * 2 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.SelectComplexProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.SelectComplexProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullPropertyTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 | using Microsoft.EntityFrameworkCore;
9 | using ScenarioTests;
10 | using VerifyXunit;
11 | using Xunit;
12 |
13 | namespace EntityFrameworkCore.Projectables.FunctionalTests
14 | {
15 | [UsesVerify]
16 | public class StatefullPropertyTests
17 | {
18 | public record Entity
19 | {
20 | public int Id { get; set; }
21 |
22 | [Projectable]
23 | public int Computed1 => Id;
24 |
25 | [Projectable]
26 | public int Computed2 => Id * 2;
27 | }
28 |
29 | [Fact]
30 | public Task FilterOnProjectableProperty()
31 | {
32 | using var dbContext = new SampleDbContext();
33 |
34 | var query = dbContext.Set()
35 | .Where(x => x.Computed1 == 1);
36 |
37 | return Verifier.Verify(query.ToQueryString());
38 | }
39 |
40 | [Fact]
41 | public Task SelectProjectableProperty()
42 | {
43 | using var dbContext = new SampleDbContext();
44 |
45 | var query = dbContext.Set()
46 | .Select(x => x.Computed1);
47 |
48 | return Verifier.Verify(query.ToQueryString());
49 | }
50 |
51 | [Fact]
52 | public Task FilterOnComplexProjectableProperty()
53 | {
54 | using var dbContext = new SampleDbContext();
55 |
56 | var query = dbContext.Set()
57 | .Where(x => x.Computed2 == 2);
58 |
59 | return Verifier.Verify(query.ToQueryString());
60 | }
61 |
62 | [Fact]
63 | public Task SelectComplexProjectableProperty()
64 | {
65 | using var dbContext = new SampleDbContext();
66 |
67 | var query = dbContext.Set()
68 | .Select(x => x.Computed2);
69 |
70 | return Verifier.Verify(query.ToQueryString());
71 | }
72 |
73 | [Fact]
74 | public Task CombineSelectProjectableProperties()
75 | {
76 | using var dbContext = new SampleDbContext();
77 |
78 | var query = dbContext.Set()
79 | .Select(x => x.Computed1 + x.Computed2);
80 |
81 | return Verifier.Verify(query.ToQueryString());
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.CombineSelectProjectableProperties.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.CombineSelectProjectableProperties.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] + [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.FilterOnComplexProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] * 2 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.FilterOnComplexProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] * 2 = 2
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Id] = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.SelectComplexProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.SelectComplexProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatefullSimpleFunctionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 | using Microsoft.EntityFrameworkCore;
9 | using ScenarioTests;
10 | using VerifyXunit;
11 | using Xunit;
12 |
13 | namespace EntityFrameworkCore.Projectables.FunctionalTests
14 | {
15 | [UsesVerify]
16 | public class StatefullSimpleFunctionTests
17 | {
18 | public record Entity
19 | {
20 | public int Id { get; set; }
21 |
22 | [Projectable]
23 | public int Computed1() => Id;
24 |
25 | [Projectable]
26 | public int Computed2() => Id * 2;
27 |
28 | public int Test(int i) => i;
29 | }
30 |
31 | [Fact]
32 | public Task FilterOnProjectableProperty()
33 | {
34 | using var dbContext = new SampleDbContext();
35 |
36 | var query = dbContext.Set()
37 | .Where(x => x.Computed1() == 1);
38 |
39 | return Verifier.Verify(query.ToQueryString());
40 | }
41 |
42 | [Fact]
43 | public Task SelectProjectableProperty()
44 | {
45 | using var dbContext = new SampleDbContext();
46 |
47 | var query = dbContext.Set()
48 | .Select(x => x.Computed1());
49 |
50 | return Verifier.Verify(query.ToQueryString());
51 | }
52 |
53 | [Fact]
54 | public Task FilterOnComplexProjectableProperty()
55 | {
56 | using var dbContext = new SampleDbContext();
57 |
58 | var query = dbContext.Set()
59 | .Where(x => x.Computed2() == 2);
60 |
61 | return Verifier.Verify(query.ToQueryString());
62 | }
63 |
64 | [Fact]
65 | public Task SelectComplexProjectableProperty()
66 | {
67 | using var dbContext = new SampleDbContext();
68 |
69 | var query = dbContext.Set()
70 | .Select(x => x.Computed2());
71 |
72 | return Verifier.Verify(query.ToQueryString());
73 | }
74 |
75 | [Fact]
76 | public Task CombineSelectProjectableProperties()
77 | {
78 | using var dbContext = new SampleDbContext();
79 |
80 | var query = dbContext.Set()
81 | .Select(x => x.Computed1() + x.Computed2());
82 |
83 | return Verifier.Verify(query.ToQueryString());
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE 0 = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE 0 = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.PassInVariableArguments.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__argument_0 int = 1;
2 |
3 | SELECT @__argument_0
4 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.PassInVariableArguments.verified.txt:
--------------------------------------------------------------------------------
1 | DECLARE @__argument_0 int = 1;
2 |
3 | SELECT @__argument_0
4 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 0
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 0
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessComplexFunctionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 | using EntityFrameworkCore.Projectables.Services;
9 | using Microsoft.EntityFrameworkCore;
10 | using ScenarioTests;
11 | using VerifyXunit;
12 | using Xunit;
13 |
14 | namespace EntityFrameworkCore.Projectables.FunctionalTests
15 | {
16 | [UsesVerify]
17 | public class StatelessComplexFunctionTests
18 | {
19 | public record Entity
20 | {
21 | public int Id { get; set; }
22 |
23 | [Projectable]
24 | public int Computed(int argument1) => argument1;
25 | }
26 |
27 |
28 | [Fact]
29 | public Task FilterOnProjectableProperty()
30 | {
31 | using var dbContext = new SampleDbContext();
32 |
33 | var query = dbContext.Set().AsQueryable()
34 | .Where(x => x.Computed(0) == 1);
35 |
36 | return Verifier.Verify(query.ToQueryString());
37 | }
38 |
39 | [Fact]
40 | public Task SelectProjectableProperty()
41 | {
42 | using var dbContext = new SampleDbContext();
43 |
44 | var query = dbContext.Set()
45 | .Select(x => x.Computed(0));
46 |
47 | return Verifier.Verify(query.ToQueryString());
48 | }
49 |
50 | [Fact]
51 | public Task PassInVariableArguments()
52 | {
53 | using var dbContext = new SampleDbContext();
54 |
55 | var argument = 1;
56 | var query = dbContext.Set()
57 | .Select(x => x.Computed(argument));
58 |
59 | return Verifier.Verify(query.ToQueryString());
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessPropertyTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE 0 = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessPropertyTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 0
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessSimpleFunctionTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE 0 = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessSimpleFunctionTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id]
2 | FROM [Entity] AS [e]
3 | WHERE 0 = 1
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessSimpleFunctionTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 0
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessSimpleFunctionTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT 0
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StatelessSimpleFunctionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
8 | using Microsoft.EntityFrameworkCore;
9 | using ScenarioTests;
10 | using VerifyXunit;
11 | using Xunit;
12 |
13 | namespace EntityFrameworkCore.Projectables.FunctionalTests
14 | {
15 | [UsesVerify]
16 | public class StatelessSimpleFunctionTests
17 | {
18 | public record Entity
19 | {
20 | public int Id { get; set; }
21 |
22 | [Projectable]
23 | public int Computed() => 0;
24 | }
25 |
26 | [Fact]
27 | public Task FilterOnProjectableProperty()
28 | {
29 | using var dbContext = new SampleDbContext();
30 |
31 | var query = dbContext.Set().AsQueryable()
32 | .Where(x => x.Computed() == 1);
33 |
34 | return Verifier.Verify(query.ToQueryString());
35 | }
36 |
37 | [Fact]
38 | public Task SelectProjectableProperty()
39 | {
40 | using var dbContext = new SampleDbContext();
41 |
42 | var query = dbContext.Set()
43 | .Select(x => x.Computed());
44 |
45 | return Verifier.Verify(query.ToQueryString());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StaticMembersTests.FilterOnProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Price]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Price] > 1.0E0
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StaticMembersTests.FilterOnProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id], [e].[Price]
2 | FROM [Entity] AS [e]
3 | WHERE [e].[Price] > 1.0E0
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/StaticMembersTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using EntityFrameworkCore.Projectables.Extensions;
8 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
9 | using Microsoft.EntityFrameworkCore;
10 | using ScenarioTests;
11 | using VerifyXunit;
12 | using Xunit;
13 |
14 | namespace EntityFrameworkCore.Projectables.FunctionalTests
15 | {
16 | [UsesVerify]
17 | public class StaticMembersTests
18 | {
19 | public static class Constants
20 | {
21 | public static readonly double ExpensiveThreshold = 1;
22 | }
23 |
24 | public record Entity
25 | {
26 | public int Id { get; set; }
27 |
28 | public double Price { get; set; }
29 |
30 | [Projectable]
31 | public bool IsExpensive => Price > Constants.ExpensiveThreshold;
32 | }
33 |
34 | [Fact]
35 | public Task FilterOnProjectableProperty()
36 | {
37 | using var dbContext = new SampleDbContext(Infrastructure.CompatibilityMode.Full);
38 |
39 | var query = dbContext.Set()
40 | .Where(x => x.IsExpensive);
41 |
42 | return Verifier.Verify(query.ToQueryString());
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/TypeNameQualificationTests.SelectProjectableProperty.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e2].[Id], [e2].[EntityId], [e2].[ParentId]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN (
4 | SELECT [e1].[Id], [e1].[EntityId], [e1].[ParentId]
5 | FROM (
6 | SELECT [e0].[Id], [e0].[EntityId], [e0].[ParentId], ROW_NUMBER() OVER(PARTITION BY [e0].[EntityId] ORDER BY [e0].[Id]) AS [row]
7 | FROM [Entity] AS [e0]
8 | ) AS [e1]
9 | WHERE [e1].[row] <= 1
10 | ) AS [e2] ON [e].[Id] = [e2].[EntityId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/TypeNameQualificationTests.SelectProjectableProperty.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [t0].[Id], [t0].[EntityId], [t0].[ParentId]
2 | FROM [Entity] AS [e]
3 | LEFT JOIN (
4 | SELECT [t].[Id], [t].[EntityId], [t].[ParentId]
5 | FROM (
6 | SELECT [e0].[Id], [e0].[EntityId], [e0].[ParentId], ROW_NUMBER() OVER(PARTITION BY [e0].[EntityId] ORDER BY [e0].[Id]) AS [row]
7 | FROM [Entity] AS [e0]
8 | ) AS [t]
9 | WHERE [t].[row] <= 1
10 | ) AS [t0] ON [e].[Id] = [t0].[EntityId]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/TypeNameQualificationTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
7 | using Microsoft.EntityFrameworkCore;
8 | using VerifyXunit;
9 | using Xunit;
10 |
11 | namespace EntityFrameworkCore.Projectables.FunctionalTests
12 | {
13 | [UsesVerify]
14 | public class TypeNameQualificationTests
15 | {
16 | public record Entity
17 | {
18 | public int Id { get; set; }
19 |
20 | public int? ParentId { get; set; }
21 |
22 | public ICollection Children { get; } = new List();
23 |
24 | [Projectable]
25 | public Entity? FirstChild =>
26 | Children.OrderBy(x => x.Id).FirstOrDefault();
27 | }
28 |
29 | [Fact]
30 | public Task SelectProjectableProperty()
31 | {
32 | using var dbContext = new SampleDbContext();
33 |
34 | var query = dbContext.Set()
35 | .Select(x => x.FirstChild);
36 |
37 | return Verifier.Verify(query.ToQueryString());
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/UseMemberBodyPropertyTests.UseMemberPropertyExpression.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 3
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/UseMemberBodyPropertyTests.UseMemberPropertyExpression.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 3
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/UseMemberBodyPropertyTests.UseMemberPropertyGenerated.DotNet9_0.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/UseMemberBodyPropertyTests.UseMemberPropertyGenerated.verified.txt:
--------------------------------------------------------------------------------
1 | SELECT [e].[Id] * 2
2 | FROM [Entity] AS [e]
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.FunctionalTests/UseMemberBodyPropertyTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.SqlTypes;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Linq.Expressions;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using EntityFrameworkCore.Projectables.FunctionalTests.Helpers;
10 | using Microsoft.EntityFrameworkCore;
11 | using ScenarioTests;
12 | using VerifyXunit;
13 | using Xunit;
14 |
15 | namespace EntityFrameworkCore.Projectables.FunctionalTests
16 | {
17 | [UsesVerify]
18 | public class UseMemberBodyPropertyTests
19 | {
20 | public record Entity
21 | {
22 | public int Id { get; set; }
23 |
24 | [Projectable(UseMemberBody = nameof(Computed2))]
25 | public int Computed1 => Id;
26 |
27 | private int Computed2 => Id * 2;
28 |
29 | [Projectable(UseMemberBody = nameof(Computed4))]
30 | public int Computed3 => Id;
31 |
32 | private static Expression> Computed4 => x => x.Id * 3;
33 | }
34 |
35 | [Fact]
36 | public Task UseMemberPropertyGenerated()
37 | {
38 | using var dbContext = new SampleDbContext();
39 |
40 | var query = dbContext.Set()
41 | .Select(x => x.Computed1);
42 |
43 | return Verifier.Verify(query.ToQueryString());
44 | }
45 |
46 | [Fact]
47 | public Task UseMemberPropertyExpression()
48 | {
49 | using var dbContext = new SampleDbContext();
50 |
51 | var query = dbContext.Set()
52 | .Select(x => x.Computed3);
53 |
54 | return Verifier.Verify(query.ToQueryString());
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/EntityFrameworkCore.Projectables.Generator.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | all
25 | runtime; build; native; contentfiles; analyzers; buildtransitive
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ArgumentlessProjectableComputedMethod.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using EntityFrameworkCore.Projectables;
5 | using Foo;
6 |
7 | namespace EntityFrameworkCore.Projectables.Generated
8 | {
9 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
10 | static class Foo_C_Foo
11 | {
12 | static global::System.Linq.Expressions.Expression> Expression()
13 | {
14 | return (global::Foo.C @this) => 0;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.BaseMemberExplicitReference.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using Projectables.Repro;
5 |
6 | namespace EntityFrameworkCore.Projectables.Generated
7 | {
8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
9 | static class Projectables_Repro_Derived_Bar
10 | {
11 | static global::System.Linq.Expressions.Expression> Expression()
12 | {
13 | return (global::Projectables.Repro.Derived @this) => @this.Foo;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.BaseMemberImplicitReference.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using Projectables.Repro;
5 |
6 | namespace EntityFrameworkCore.Projectables.Generated
7 | {
8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
9 | static class Projectables_Repro_Derived_Bar
10 | {
11 | static global::System.Linq.Expressions.Expression> Expression()
12 | {
13 | return (global::Projectables.Repro.Derived @this) => @this.Foo;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.BaseMethodExplicitReference.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using Projectables.Repro;
5 |
6 | namespace EntityFrameworkCore.Projectables.Generated
7 | {
8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
9 | static class Projectables_Repro_Derived_Bar
10 | {
11 | static global::System.Linq.Expressions.Expression> Expression()
12 | {
13 | return (global::Projectables.Repro.Derived @this) => @this.Foo();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.BaseMethorImplicitReference.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using Projectables.Repro;
5 |
6 | namespace EntityFrameworkCore.Projectables.Generated
7 | {
8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
9 | static class Projectables_Repro_Derived_Bar
10 | {
11 | static global::System.Linq.Expressions.Expression> Expression()
12 | {
13 | return (global::Projectables.Repro.Derived @this) => @this.Foo();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.BooleanSimpleTernary_WithRewriteSupport_IsBeingRewritten.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using EntityFrameworkCore.Projectables;
6 | using Foo;
7 |
8 | namespace EntityFrameworkCore.Projectables.Generated
9 | {
10 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
11 | static class Foo_C_Test
12 | {
13 | static global::System.Linq.Expressions.Expression> Expression()
14 | {
15 | return (object x) => (x != null ? (x.Equals(4)) : ( bool ? )null) == false;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.Cast.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using Projectables.Repro;
5 |
6 | namespace EntityFrameworkCore.Projectables.Generated
7 | {
8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
9 | static class Projectables_Repro_SomeExtensions_AsSomeResult
10 | {
11 | static global::System.Linq.Expressions.Expression> Expression()
12 | {
13 | return (global::Projectables.Repro.SomeEntity e) => ((global::Projectables.Repro.SuperEntity)e).Superpower;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ConstMember.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_Foo_IdWithBar
13 | {
14 | static global::System.Linq.Expressions.Expression> Expression()
15 | {
16 | return (global::Foo.Foo @this) => @this.Id + global::Foo.Foo.Bar;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ConstMember2.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_Foo_IdWithBar
13 | {
14 | static global::System.Linq.Expressions.Expression> Expression()
15 | {
16 | return (global::Foo.Foo @this) => @this.Id + global::Foo.Constants.Bar;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ConstMember3.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_Foo_IdWithBar
13 | {
14 | static global::System.Linq.Expressions.Expression> Expression()
15 | {
16 | return (global::Foo.Foo @this) => @this.Id + global::Foo.Foo.Bar;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.DeclarationTypeNamesAreGettingFullyQualified.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_EntityExtensions_Entity_Something
13 | {
14 | static global::System.Linq.Expressions.Expression> Expression()
15 | {
16 | return (global::Foo.EntityExtensions.Entity entity) => entity;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.DefaultValuesGetRemoved.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 |
5 | namespace EntityFrameworkCore.Projectables.Generated
6 | {
7 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
8 | static class _Foo_Calculate
9 | {
10 | static global::System.Linq.Expressions.Expression> Expression()
11 | {
12 | return (global::Foo @this, int i) => i;
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.EnumAccessor.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 |
5 | namespace EntityFrameworkCore.Projectables.Generated
6 | {
7 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
8 | static class _SomeExtensions_Test
9 | {
10 | static global::System.Linq.Expressions.Expression> Expression()
11 | {
12 | return (global::SomeFlag f) => f == global::SomeFlag.Foo;
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.FooOrBar.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using EntityFrameworkCore.Projectables;
4 | using System.Collections.Generic;
5 | using Projectables.Repro;
6 |
7 | namespace EntityFrameworkCore.Projectables.Generated
8 | {
9 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
10 | static class Projectables_Repro_SomeEntity_FooOrBar
11 | {
12 | static global::System.Linq.Expressions.Expression> Expression()
13 | {
14 | return (global::Projectables.Repro.SomeEntity @this) => @this.Foo != null ? @this.Foo : @this.Bar;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericClassesWithContraints_AreRewritten.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_Entity_FullName
13 | where T : global::Foo.TypedObject where TEnum : struct, global::System.Enum
14 | {
15 | static global::System.Linq.Expressions.Expression, string>> Expression()
16 | {
17 | return (global::Foo.Entity @this) => $"{(@this.FirstName)} {(@this.LastName)} {(@this.SomeSubobject.SomeProp)}";
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericClassesWithTypeContraints_AreRewritten.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_Entity_FullName
13 | {
14 | static global::System.Linq.Expressions.Expression, string>> Expression()
15 | {
16 | return (global::Foo.Entity @this) => $"{(@this.FirstName)} {(@this.LastName)} {(@this.SomeSubobject)}";
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericMethods_AreRewritten.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_EntityExtensions_EnforceString
13 | {
14 | static global::System.Linq.Expressions.Expression> Expression()
15 | where T : unmanaged
16 | {
17 | return (T value) => value.ToString();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericNullableReferenceTypesAreBeingEliminated.verified.txt:
--------------------------------------------------------------------------------
1 | //
2 | #nullable disable
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using EntityFrameworkCore.Projectables;
7 | using Foo;
8 |
9 | namespace EntityFrameworkCore.Projectables.Generated
10 | {
11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
12 | static class Foo_C_NextFoo
13 | {
14 | static global::System.Linq.Expressions.Expression, global::System.Collections.Generic.List, global::System.Collections.Generic.List