├── .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>> Expression() 15 | { 16 | return (global::System.Collections.Generic.List input, global::System.Collections.Generic.List nullablePrimitiveArgument) => input; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericTypes.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 _EntiyBase_GetId 9 | { 10 | static global::System.Linq.Expressions.Expression> Expression() 11 | { 12 | return () => default; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericTypesWithConstraints.verified.txt: -------------------------------------------------------------------------------- 1 | // 2 | #nullable disable 3 | using System; 4 | using EntityFrameworkCore.Projectables; 5 | 6 | namespace EntityFrameworkCore.Projectables.Generated 7 | { 8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] 9 | static class _EntityBase_GetId 10 | where TId : global::System.ICloneable, new() 11 | { 12 | static global::System.Linq.Expressions.Expression> Expression() 13 | { 14 | return () => default; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.InheritedMembers.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_Bar_ProjectedId 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (global::Foo.Bar @this) => @this.Id; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.IsOperator.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_A_IsB 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.A @this) => @this is global::Foo.B; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.MinimalProjectableComputedProperty.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) => @this.Bar; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.MixPrimaryConstructorAndProperties.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) => new global::Foo.EntityExtensions.Entity(entity.Id) 17 | { 18 | FullName = entity.FullName 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.MoreComplexProjectableComputedProperty.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) => @this.Bar + @this.Bar + @this.Bar; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NavigationProperties.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_RootChildren 11 | { 12 | static global::System.Linq.Expressions.Expression>> Expression() 13 | { 14 | return (global::Projectables.Repro.SomeEntity @this) => @this.Parent != null ? @this.Parent.RootChildren : @this.Children; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullConditionalNullCoalesceTypeConversion.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_SomeNumber 9 | { 10 | static global::System.Linq.Expressions.Expression> Expression() 11 | { 12 | return (global::Foo fancyClass) => (fancyClass != null ? (fancyClass.FancyNumber) : ( int ? )null) ?? 3; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableElementAndMemberBinding_WithIgnoreSupport_IsBeingRewritten.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_GetFirstRelatedIgnoreNulls 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (global::Foo.EntityExtensions.Entity entity) => entity.RelatedEntities[0]; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableElementAndMemberBinding_WithRewriteSupport_IsBeingRewritten.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_GetFirstRelatedIgnoreNulls 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (global::Foo.EntityExtensions.Entity entity) => (entity != null ? ((entity.RelatedEntities != null ? (entity.RelatedEntities[0]) : (global::Foo.EntityExtensions.Entity)null)) : (global::Foo.EntityExtensions.Entity)null); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableElementBinding_WithIgnoreSupport_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_GetFirst 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => input[0].ToString(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableElementBinding_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_GetFirst 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => (input != null ? (input[0].ToString()) : ( string )null); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableMemberBinding_WithIgnoreSupport_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_GetLength 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => input.Length; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableMemberBinding_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_GetLength 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => (input != null ? (input.Length) : ( int ? )null); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableParameters_WithRewriteSupport_IsBeingRewritten.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_GetFirstName 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (global::Foo.EntityExtensions.Entity entity) => (entity.FullName != null ? (entity.FullName.Substring((entity.FullName != null ? (entity.FullName.IndexOf(' ')) : ( int ? )null) ?? 0)) : ( string )null); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableReferenceTypeCastOperatorGetsEliminated.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_NullableReferenceType 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (object input) => (string)input; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableReferenceTypesAreBeingEliminated.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_NextFoo 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (object unusedArgument, int? nullablePrimitiveArgument) => null; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableSimpleElementBinding_WithIgnoreSupport_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_GetFirst 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => input[0]; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableSimpleElementBinding_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_GetFirst 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (string input) => (input != null ? (input[0]) : ( char ? )null); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.NullableValueCastOperatorsPersist.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_NullableValueType 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (object input) => (int? )input; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ParamsModifiedGetsRemoved.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_First 9 | { 10 | static global::System.Linq.Expressions.Expression> Expression() 11 | { 12 | return (global::Foo @this, int[] all) => all[0]; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableComputedMethodWithMultipleArguments.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, int a, string b, object d) => a; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableComputedMethodWithSingleArgument.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, int i) => i; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableComputedPropertyMethod.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) => @this.Bar(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableComputedPropertyUsingThis.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) => @this.Bar; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod.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_Foo 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.D d) => 1; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod2.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_Foo 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (int i) => i; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.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_Foo1 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (int i) => i; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.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_Foo1 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (object i) => global::Foo.C.Foo1(i); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectablePropertyToNavigationalProperty.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_Foo 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.C @this) => global::System.Linq.Enumerable.First(@this.Dees); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.RelationalProperty.verified.txt: -------------------------------------------------------------------------------- 1 | // 2 | #nullable disable 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | using EntityFrameworkCore.Projectables; 7 | using Foos; 8 | 9 | namespace EntityFrameworkCore.Projectables.Generated 10 | { 11 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] 12 | static class Foos_Bar_FooId 13 | { 14 | static global::System.Linq.Expressions.Expression> Expression() 15 | { 16 | return (global::Foos.Bar @this) => @this.Foo.Id; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.RequiredNamespace.verified.txt: -------------------------------------------------------------------------------- 1 | // 2 | #nullable disable 3 | using EntityFrameworkCore.Projectables; 4 | using One.Two; 5 | 6 | namespace EntityFrameworkCore.Projectables.Generated 7 | { 8 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] 9 | static class One_Two_Bar_Method 10 | { 11 | static global::System.Linq.Expressions.Expression> Expression() 12 | { 13 | return (global::One.Two.Bar @this) => global::One.IntExtensions.AddOne(1); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SimpleProjectableComputedInNestedClassProperty.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_D_Foo 11 | { 12 | static global::System.Linq.Expressions.Expression> Expression() 13 | { 14 | return (global::Foo.C.D @this) => @this.Bar + 1; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SimpleProjectableComputedProperty.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) => @this.Bar + 1; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SimpleProjectableMethod.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) => 1; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SimpleProjectableProperty.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) => 1; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.StaticMembers.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.StaticMembers2.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.StaticMethodWithNoParameters.verified.txt: -------------------------------------------------------------------------------- 1 | // 2 | #nullable disable 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | using EntityFrameworkCore.Projectables; 7 | 8 | namespace EntityFrameworkCore.Projectables.Generated 9 | { 10 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] 11 | static class _Foo_Zero 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return () => 0; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.StaticMethodWithParameters.verified.txt: -------------------------------------------------------------------------------- 1 | // 2 | #nullable disable 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | using EntityFrameworkCore.Projectables; 7 | 8 | namespace EntityFrameworkCore.Projectables.Generated 9 | { 10 | [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] 11 | static class _Foo_Zero 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (int x) => 0; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.StringInterpolationWithParenthesis_NoParenthesisAdded.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_Status 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.C @this) => @this.ValidationDate != null ? $"Validation date : ({(global::Foo.MyExtensions.ToDateString(@this.ValidationDate.Value))})" : ""; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.StringInterpolationWithStaticCall_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_Status 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.C @this) => @this.ValidationDate != null ? $"Validation date : ({(global::Foo.MyExtensions.ToDateString(@this.ValidationDate.Value))})" : ""; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SwitchExpressionWithConstantPattern.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_SomeNumber 9 | { 10 | static global::System.Linq.Expressions.Expression> Expression() 11 | { 12 | return (global::Foo @this, int input) => input == 1 ? 2 : input == 3 ? 4 : input == 4 && @this.FancyNumber == 12 ? 48 : 1000; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.SwitchExpressionWithTypePattern.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 _ItemMapper_ToData 9 | { 10 | static global::System.Linq.Expressions.Expression> Expression() 11 | { 12 | return (global::Item item) => item.GetType() == typeof(GroupItem) ? new global::GroupData(((GroupItem)item).Id, ((GroupItem)item).Name, ((GroupItem)item).Description) : item.GetType() == typeof(DocumentItem) ? new global::DocumentData(((DocumentItem)item).Id, ((DocumentItem)item).Name, ((DocumentItem)item).Priority) : null !; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.TypesInBodyGetsFullyQualified.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_Foo 12 | { 13 | static global::System.Linq.Expressions.Expression> Expression() 14 | { 15 | return (global::Foo.C @this) => global::System.Linq.Enumerable.Count(global::System.Linq.Enumerable.OfType(@this.Dees)); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Tests/EntityFrameworkCore.Projectables.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Tests/Services/ExpressionArgumentReplacerTests.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 | using Xunit; 9 | 10 | namespace EntityFrameworkCore.Projectables.Tests.Services 11 | { 12 | public class ExpressionArgumentReplacerTests 13 | { 14 | [Fact] 15 | public void VisitParameter_MapsParametersWithArguments() 16 | { 17 | var parameter = Expression.Parameter(typeof(int)); 18 | var argument = Expression.Constant(1); 19 | var subject = new ExpressionArgumentReplacer() { 20 | ParameterArgumentMapping = { 21 | { parameter, argument } 22 | } 23 | }; 24 | 25 | var result = subject.Visit(parameter); 26 | 27 | Assert.Equal(argument, result); 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/EntityFrameworkCore.Projectables.Tests/Services/ProjectionExpressionClassNameGeneratorTests.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 Xunit; 8 | 9 | namespace EntityFrameworkCore.Projectables.Tests.Services 10 | { 11 | public class ProjectionExpressionClassNameGeneratorTests 12 | { 13 | [Theory] 14 | [InlineData("ns", new string[] { "a" }, "m", "ns_a_m")] 15 | [InlineData("ns", new string[] { "a", "b" }, "m", "ns_a_b_m")] 16 | [InlineData(null, new string[] { "a" }, "m", "_a_m")] 17 | [InlineData("ns", new string[] { "a`1" }, "m", "ns_a_m`1" )] 18 | [InlineData("ns", new string[] { "a`1", "b`1" }, "m", "ns_a_b_m`2")] 19 | public void GenerateName(string? namespaceName, string[] nestedTypeNames, string memberName, string expected) 20 | { 21 | var result = ProjectionExpressionClassNameGenerator.GenerateName(namespaceName, nestedTypeNames, memberName); 22 | 23 | Assert.Equal(expected, result); 24 | } 25 | 26 | [Fact] 27 | public void GeneratedFullName() 28 | { 29 | var expected = $"{ProjectionExpressionClassNameGenerator.Namespace}.{ProjectionExpressionClassNameGenerator.GenerateName("a", new[] { "b" }, "m")}"; 30 | var result = ProjectionExpressionClassNameGenerator.GenerateFullName("a", new [] { "b" }, "m"); 31 | 32 | Assert.Equal(expected, result); 33 | } 34 | } 35 | } 36 | --------------------------------------------------------------------------------