From 5bb52123a10f4ba9fcbb5b8fb5b1763391057f50 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 25 Oct 2022 12:01:31 +0200 Subject: [PATCH 1/7] Extended unit tests --- .../Test01NestedExpressions.cs | 44 +++++++ .../NestedExpressionsTests.cs | 121 ++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs index 9dfa7b81..2e5c97ab 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs @@ -1,5 +1,6 @@ using System.Linq; using DelegateDecompiler.EntityFramework.Tests.EfItems; +using DelegateDecompiler.EntityFramework.Tests.EfItems.Abstracts; using DelegateDecompiler.EntityFramework.Tests.Helpers; using NUnit.Framework; @@ -68,5 +69,48 @@ public void TestSubqueryAsContextExtensionMethod() env.CompareAndLogList(linq, dd); } } + + [Test] +#if EF_CORE && !EF_CORE3 && !EF_CORE5 + [Ignore("Not natively supported in EF_CORE < 3")] +#endif + public void TestSubqueryAsVariableReference() + { + using (var env = new MethodEnvironment(classEnv)) + { + //ATTEMPT + env.AboutToUseDelegateDecompiler(); + + var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus"); + var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); + + + var list = query.ToList(); + + //VERIFY + Assert.AreEqual(1, list.Count()); + } + } + + [Test] +#if EF_CORE && !EF_CORE3 && !EF_CORE5 + [Ignore("Not natively supported in EF_CORE < 3")] +#endif + public void TestFilterWithSubqueryReference() + { + using (var env = new MethodEnvironment(classEnv)) + { + //SETUP + var linq = env.Db.EfParents.Any(x => env.Db.EfParents.Where(p => p.Children.Count() == 0).Contains(x)); + + //ATTEMPT + env.AboutToUseDelegateDecompiler(); + var referencedQuery = env.Db.EfParents.Where(p => p.CountChildren == 0); + var dd = env.Db.EfParents.Decompile().Any(x => referencedQuery.Contains(x)); + + //VERIFY + env.CompareAndLogSingleton(linq, dd); + } + } } } \ No newline at end of file diff --git a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs index d19e5dd5..dafa631b 100644 --- a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs +++ b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using NUnit.Framework; namespace DelegateDecompiler.Tests @@ -14,6 +15,21 @@ public class NestedExpressionsTests : DecompilerTestsBase int M1() => 0; static int M2() => 0; + readonly IQueryable fQref1 = Enumerable.Empty().AsQueryable(); + static IQueryable fQref2 = Enumerable.Empty().AsQueryable(); + [Decompile] + IQueryable pQref1 => Enumerable.Empty().AsQueryable(); + [Decompile] + static IQueryable pQref2 => Enumerable.Empty().AsQueryable(); + [Decompile] + IQueryable MQref1() => Enumerable.Empty().AsQueryable(); + [Decompile] + static IQueryable MQref2() => Enumerable.Empty().AsQueryable(); + [Decompile] + IQueryable ParamedMQref1(int floor) => Enumerable.Empty().AsQueryable().Where(x => x >= floor); + [Decompile] + static IQueryable ParamedMQref2(int floor) => Enumerable.Empty().AsQueryable().Where(x => x >= floor); + [Test] public void TestNestedExpression() { @@ -178,5 +194,110 @@ public void TestFuncWithStaticMethodClosure() ints => ints.SingleOrDefault(i => i == M2()) ); } + + [Test] + //[Test, Ignore("Difference is expected")] + public void TestQueryableBoundAsVariable() + { + IQueryable query = Enumerable.Empty().AsQueryable().Where(i => i >= 0); + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => query + ); + } + + [Test] + //[Test, Ignore("Difference is expected")] + public void TestQueryableRefFromField() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => fQref1.Where(i => i >= 0) + ); + } + + [Test] + //[Test, Ignore("Difference is expected")] + public void TestQueryableRefFromStaticField() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => fQref2.Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromProperty() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => pQref1.Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromStaticProperty() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => pQref2.Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromMethod() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => MQref1().Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromStaticMethod() + { + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), + ints => MQref2().Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromMethodWithBoundParameters() + { + var floor = 10; + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(x => x >= floor).Where(i => i >= 0), + ints => ParamedMQref1(floor).Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromStaticMethoWithBoundParameters() + { + var floor = 10; + Test, IQueryable>>( + ints => Enumerable.Empty().AsQueryable().Where(x => x >= floor).Where(i => i >= 0), + ints => ParamedMQref1(floor).Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromMethodWithUnboundParameters() + { + Test, int, IQueryable>>( + (ints, floor) => Enumerable.Empty().AsQueryable().Where(x => x >= floor).Where(i => i >= 0), + (ints, floor) => ParamedMQref1(floor).Where(i => i >= 0) + ); + } + + [Test] + public void TestQueryableRefFromStaticMethoWithUnboundParameters() + { + Test, int, IQueryable>>( + (ints, floor) => Enumerable.Empty().AsQueryable().Where(x => x >= floor).Where(i => i >= 0), + (ints, floor) => ParamedMQref1(floor).Where(i => i >= 0) + ); + } } } From 8b2c80c3584d5dec5822d8b3c41fbf5abf8bc850 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 25 Oct 2022 16:10:28 +0200 Subject: [PATCH 2/7] PR #209 merged into OptimizeExpressionVisitor --- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 30 +++++++++++++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- .../AsyncDecompiledQueryProvider.cs | 6 ++-- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../AsyncDecompiledQueryProvider.cs | 8 ++--- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 13 ++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- .../AsyncDecompiledQueryProvider.cs | 4 +-- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 25 ++++++++++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- .../NestedExpressionsTests.cs | 9 ++---- src/DelegateDecompiler/DecompileExtensions.cs | 2 +- .../OptimizeExpressionVisitor.cs | 26 +++++++++++++++- 18 files changed, 127 insertions(+), 41 deletions(-) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 82a7ccf4..152c3d5c 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -147,7 +147,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 0f61cb3a..7be854a9 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -849,7 +849,7 @@ SELECT ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL @@ -874,6 +874,32 @@ SELECT ) AS [Project4] ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL +SELECT + CASE WHEN ( EXISTS (SELECT + 1 AS [C1] + FROM [dbo].[EfParents] AS [Extent1] + WHERE EXISTS (SELECT + 1 AS [C1] + FROM ( SELECT + [Extent2].[EfParentId] AS [EfParentId], + (SELECT + COUNT(1) AS [A1] + FROM [dbo].[EfChilds] AS [Extent3] + WHERE [Extent2].[EfParentId] = [Extent3].[EfParentId]) AS [C1] + FROM [dbo].[EfParents] AS [Extent2] + ) AS [Project1] + WHERE (0 = [Project1].[C1]) AND ([Project1].[EfParentId] = [Extent1].[EfParentId]) + ) + )) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1] + FROM ( SELECT 1 AS X ) AS [SingleRowTable1] +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 1a7a23c4..69919226 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs index 177fb1de..ef68fdab 100644 --- a/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs @@ -43,7 +43,7 @@ public override IQueryable CreateQuery(Expression expression) public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new AsyncDecompiledQueryable(this, inner.CreateQuery(decompiled)); } @@ -54,7 +54,7 @@ public Task ExecuteAsync(Expression expression, CancellationToken cancel { throw new InvalidOperationException("The source IQueryProvider doesn't implement IDbAsyncQueryProvider."); } - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return asyncProvider.ExecuteAsync(decompiled, cancellationToken); } @@ -65,7 +65,7 @@ public Task ExecuteAsync(Expression expression, CancellationTo { throw new InvalidOperationException("The source IQueryProvider doesn't implement IDbAsyncQueryProvider."); } - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return asyncProvider.ExecuteAsync(decompiled, cancellationToken); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 457d5b64..655606e0 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 3b763afd..a13d3ec9 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 34cf5223..1567f73b 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs index 37e48023..96b4e3c9 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs @@ -39,7 +39,7 @@ protected IAsyncQueryProvider AsyncQueryProvider // ReSharper disable once VirtualMemberNeverOverridden.Global public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (TResult)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled, cancellationToken); } @@ -95,19 +95,19 @@ public AsyncDecompiledQueryProvider(IQueryProvider inner) public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new EntityQueryable(this, decompiled); } public virtual IAsyncEnumerable ExecuteAsync(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (IAsyncEnumerable)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled); } public new virtual Task ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (Task)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled, cancellationToken); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 359b7016..da3bfdfc 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -146,7 +146,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 1e001df1..4ba4cbed 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -506,13 +506,22 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL + +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index add4b1f9..82afbfa5 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs index 4bdf7b2e..9b51e397 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs @@ -27,14 +27,14 @@ IAsyncQueryProvider AsyncQueryProvider public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return AsyncQueryProvider.ExecuteAsync(decompiled, cancellationToken); } [SuppressMessage("EntityFramework", "EF1001")] public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new EntityQueryable(this, decompiled); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 359b7016..da3bfdfc 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -146,7 +146,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index d36f0da9..d6bc36f0 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -775,7 +775,7 @@ WHERE [e].[StartDate] > '2000-01-01T00:00:00.0000000' ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL @@ -786,6 +786,27 @@ SELECT [e].[EfParentId] AS [ParentId], COALESCE(( FROM [EfParents] AS [e] ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL +SELECT CASE + WHEN EXISTS ( + SELECT 1 + FROM [EfParents] AS [e] + WHERE EXISTS ( + SELECT 1 + FROM [EfParents] AS [e0] + WHERE (( + SELECT COUNT(*) + FROM [EfChildren] AS [e1] + WHERE [e0].[EfParentId] = [e1].[EfParentId]) = 0) AND ([e0].[EfParentId] = [e].[EfParentId]))) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index add4b1f9..82afbfa5 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs index dafa631b..707fe914 100644 --- a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs +++ b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs @@ -195,8 +195,7 @@ public void TestFuncWithStaticMethodClosure() ); } - [Test] - //[Test, Ignore("Difference is expected")] + [Test, Ignore("Difference is expected")] public void TestQueryableBoundAsVariable() { IQueryable query = Enumerable.Empty().AsQueryable().Where(i => i >= 0); @@ -206,8 +205,7 @@ public void TestQueryableBoundAsVariable() ); } - [Test] - //[Test, Ignore("Difference is expected")] + [Test, Ignore("Difference is expected")] public void TestQueryableRefFromField() { Test, IQueryable>>( @@ -216,8 +214,7 @@ public void TestQueryableRefFromField() ); } - [Test] - //[Test, Ignore("Difference is expected")] + [Test, Ignore("Difference is expected")] public void TestQueryableRefFromStaticField() { Test, IQueryable>>( diff --git a/src/DelegateDecompiler/DecompileExtensions.cs b/src/DelegateDecompiler/DecompileExtensions.cs index 6b688d33..32ddd21d 100644 --- a/src/DelegateDecompiler/DecompileExtensions.cs +++ b/src/DelegateDecompiler/DecompileExtensions.cs @@ -24,7 +24,7 @@ public static LambdaExpression Decompile(this Delegate @delegate) { {expression.Parameters[0], Expression.Constant(@delegate.Target)} }); - var transformed = visitor.Visit(expression.Body); + var transformed = visitor.Visit(expression.Body).Optimize(); return Expression.Lambda(transformed, expression.Parameters.Skip(1)); } diff --git a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs index f397f4f3..d1b7816f 100644 --- a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs +++ b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace DelegateDecompiler { @@ -339,6 +341,22 @@ node.Operand is BinaryExpression binary && return base.VisitUnary(node); } + protected override Expression VisitMember(MemberExpression node) + { + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + if (Configuration.Instance.ShouldDecompile(node.Member)) + { + return Visit(node.Decompile()); + } + else if (!(node.Expression is ParameterExpression) && node.Member is FieldInfo) + { + return Visit((node.Evaluate()).Expression.Decompile()); + } + } + return base.VisitMember(node); + } + protected override Expression VisitMethodCall(MethodCallExpression node) { if (node.Method.Name == nameof(Expression.Lambda) && @@ -347,7 +365,13 @@ protected override Expression VisitMethodCall(MethodCallExpression node) var call = base.VisitMethodCall(node); return LinqExpressionUnwrapper.Unwrap(call); } - + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + if (Configuration.Instance.ShouldDecompile(node.Method)) + { + return Visit(node.Decompile()); + } + } return base.VisitMethodCall(node); } From 97ad4c92483b6f16baf67df55f773650384a3ef6 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 25 Oct 2022 12:01:31 +0200 Subject: [PATCH 3/7] Extended unit tests --- .../Test01NestedExpressions.cs | 44 +++++++++++++++++++ .../NestedExpressionsTests.cs | 1 + 2 files changed, 45 insertions(+) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs index 9dfa7b81..2e5c97ab 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs @@ -1,5 +1,6 @@ using System.Linq; using DelegateDecompiler.EntityFramework.Tests.EfItems; +using DelegateDecompiler.EntityFramework.Tests.EfItems.Abstracts; using DelegateDecompiler.EntityFramework.Tests.Helpers; using NUnit.Framework; @@ -68,5 +69,48 @@ public void TestSubqueryAsContextExtensionMethod() env.CompareAndLogList(linq, dd); } } + + [Test] +#if EF_CORE && !EF_CORE3 && !EF_CORE5 + [Ignore("Not natively supported in EF_CORE < 3")] +#endif + public void TestSubqueryAsVariableReference() + { + using (var env = new MethodEnvironment(classEnv)) + { + //ATTEMPT + env.AboutToUseDelegateDecompiler(); + + var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus"); + var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); + + + var list = query.ToList(); + + //VERIFY + Assert.AreEqual(1, list.Count()); + } + } + + [Test] +#if EF_CORE && !EF_CORE3 && !EF_CORE5 + [Ignore("Not natively supported in EF_CORE < 3")] +#endif + public void TestFilterWithSubqueryReference() + { + using (var env = new MethodEnvironment(classEnv)) + { + //SETUP + var linq = env.Db.EfParents.Any(x => env.Db.EfParents.Where(p => p.Children.Count() == 0).Contains(x)); + + //ATTEMPT + env.AboutToUseDelegateDecompiler(); + var referencedQuery = env.Db.EfParents.Where(p => p.CountChildren == 0); + var dd = env.Db.EfParents.Decompile().Any(x => referencedQuery.Contains(x)); + + //VERIFY + env.CompareAndLogSingleton(linq, dd); + } + } } } \ No newline at end of file diff --git a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs index e786cea1..4f922b7e 100644 --- a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs +++ b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using NUnit.Framework; namespace DelegateDecompiler.Tests From 41a62f7d35d4f1ba992840d5584f48d3204894cd Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 25 Oct 2022 16:10:28 +0200 Subject: [PATCH 4/7] PR #209 merged into OptimizeExpressionVisitor --- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 30 +++++++++++++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- .../AsyncDecompiledQueryProvider.cs | 6 ++-- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../AsyncDecompiledQueryProvider.cs | 8 ++--- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 13 ++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- .../AsyncDecompiledQueryProvider.cs | 4 +-- .../DetailedListOfSupportedCommands.md | 7 +++-- .../DetailedListOfSupportedCommandsWithSQL.md | 25 ++++++++++++++-- .../SummaryOfSupportedCommands.md | 6 ++-- src/DelegateDecompiler/DecompileExtensions.cs | 2 +- .../OptimizeExpressionVisitor.cs | 26 +++++++++++++++- 17 files changed, 124 insertions(+), 35 deletions(-) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 82a7ccf4..152c3d5c 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -147,7 +147,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 0f61cb3a..7be854a9 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -849,7 +849,7 @@ SELECT ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL @@ -874,6 +874,32 @@ SELECT ) AS [Project4] ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL +SELECT + CASE WHEN ( EXISTS (SELECT + 1 AS [C1] + FROM [dbo].[EfParents] AS [Extent1] + WHERE EXISTS (SELECT + 1 AS [C1] + FROM ( SELECT + [Extent2].[EfParentId] AS [EfParentId], + (SELECT + COUNT(1) AS [A1] + FROM [dbo].[EfChilds] AS [Extent3] + WHERE [Extent2].[EfParentId] = [Extent3].[EfParentId]) AS [C1] + FROM [dbo].[EfParents] AS [Extent2] + ) AS [Project1] + WHERE (0 = [Project1].[C1]) AND ([Project1].[EfParentId] = [Extent1].[EfParentId]) + ) + )) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1] + FROM ( SELECT 1 AS X ) AS [SingleRowTable1] +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 1a7a23c4..69919226 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:36 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs index 177fb1de..ef68fdab 100644 --- a/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFramework/AsyncDecompiledQueryProvider.cs @@ -43,7 +43,7 @@ public override IQueryable CreateQuery(Expression expression) public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new AsyncDecompiledQueryable(this, inner.CreateQuery(decompiled)); } @@ -54,7 +54,7 @@ public Task ExecuteAsync(Expression expression, CancellationToken cancel { throw new InvalidOperationException("The source IQueryProvider doesn't implement IDbAsyncQueryProvider."); } - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return asyncProvider.ExecuteAsync(decompiled, cancellationToken); } @@ -65,7 +65,7 @@ public Task ExecuteAsync(Expression expression, CancellationTo { throw new InvalidOperationException("The source IQueryProvider doesn't implement IDbAsyncQueryProvider."); } - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return asyncProvider.ExecuteAsync(decompiled, cancellationToken); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 457d5b64..655606e0 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 3b763afd..a13d3ec9 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 34cf5223..1567f73b 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs index 37e48023..96b4e3c9 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFrameworkCore/AsyncDecompiledQueryProvider.cs @@ -39,7 +39,7 @@ protected IAsyncQueryProvider AsyncQueryProvider // ReSharper disable once VirtualMemberNeverOverridden.Global public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (TResult)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled, cancellationToken); } @@ -95,19 +95,19 @@ public AsyncDecompiledQueryProvider(IQueryProvider inner) public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new EntityQueryable(this, decompiled); } public virtual IAsyncEnumerable ExecuteAsync(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (IAsyncEnumerable)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled); } public new virtual Task ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return (Task)MethodCache.ExecuteAsync(AsyncQueryProvider, decompiled, cancellationToken); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 359b7016..da3bfdfc 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -146,7 +146,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 1e001df1..4ba4cbed 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -506,13 +506,22 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL + +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index add4b1f9..82afbfa5 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs b/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs index 4bdf7b2e..9b51e397 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs +++ b/src/DelegateDecompiler.EntityFrameworkCore5/AsyncDecompiledQueryProvider.cs @@ -27,14 +27,14 @@ IAsyncQueryProvider AsyncQueryProvider public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return AsyncQueryProvider.ExecuteAsync(decompiled, cancellationToken); } [SuppressMessage("EntityFramework", "EF1001")] public override IQueryable CreateQuery(Expression expression) { - var decompiled = expression.Decompile(); + var decompiled = expression.Decompile().Optimize(); return new EntityQueryable(this, decompiled); } } diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 359b7016..da3bfdfc 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -146,7 +146,10 @@ More will appear as we move forward.* ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) + * Filter With Subquery Reference (line 112) +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index d36f0da9..d6bc36f0 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -775,7 +775,7 @@ WHERE [e].[StartDate] > '2000-01-01T00:00:00.0000000' ### Group: Additional Features #### [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs): - Supported - * Subquery As Context Extension Method (line 68) + * Subquery As Context Extension Method (line 69) * T-Sql executed is ```SQL @@ -786,6 +786,27 @@ SELECT [e].[EfParentId] AS [ParentId], COALESCE(( FROM [EfParents] AS [e] ``` + * Filter With Subquery Reference (line 112) + * T-Sql executed is + +```SQL +SELECT CASE + WHEN EXISTS ( + SELECT 1 + FROM [EfParents] AS [e] + WHERE EXISTS ( + SELECT 1 + FROM [EfParents] AS [e0] + WHERE (( + SELECT COUNT(*) + FROM [EfChildren] AS [e1] + WHERE [e0].[EfParentId] = [e1].[EfParentId]) = 0) AND ([e0].[EfParentId] = [e].[EfParentId]))) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END +``` + +- **Not Supported** + * Subquery As Variable Reference (line 82) diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index add4b1f9..82afbfa5 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 19:37 +## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -55,8 +55,8 @@ More will appear as we move forward.* * [DateTime](../TestGroup50Types/Test05DateTime.cs) (1 tests) ### Group: Additional Features -- Supported - * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (1 tests) +- **Partially Supported** + * [Nested Expressions](../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs) (2 of 3 tests passed) The End diff --git a/src/DelegateDecompiler/DecompileExtensions.cs b/src/DelegateDecompiler/DecompileExtensions.cs index c7dacc89..41588556 100644 --- a/src/DelegateDecompiler/DecompileExtensions.cs +++ b/src/DelegateDecompiler/DecompileExtensions.cs @@ -24,7 +24,7 @@ public static LambdaExpression Decompile(this Delegate @delegate) { {expression.Parameters[0], Expression.Constant(@delegate.Target)} }); - var transformed = visitor.Visit(expression.Body); + var transformed = visitor.Visit(expression.Body).Optimize(); return Expression.Lambda(transformed, expression.Parameters.Skip(1)); } diff --git a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs index f397f4f3..d1b7816f 100644 --- a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs +++ b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace DelegateDecompiler { @@ -339,6 +341,22 @@ node.Operand is BinaryExpression binary && return base.VisitUnary(node); } + protected override Expression VisitMember(MemberExpression node) + { + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + if (Configuration.Instance.ShouldDecompile(node.Member)) + { + return Visit(node.Decompile()); + } + else if (!(node.Expression is ParameterExpression) && node.Member is FieldInfo) + { + return Visit((node.Evaluate()).Expression.Decompile()); + } + } + return base.VisitMember(node); + } + protected override Expression VisitMethodCall(MethodCallExpression node) { if (node.Method.Name == nameof(Expression.Lambda) && @@ -347,7 +365,13 @@ protected override Expression VisitMethodCall(MethodCallExpression node) var call = base.VisitMethodCall(node); return LinqExpressionUnwrapper.Unwrap(call); } - + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + if (Configuration.Instance.ShouldDecompile(node.Method)) + { + return Visit(node.Decompile()); + } + } return base.VisitMethodCall(node); } From 62833b26f00c51ba1161ff96a75ad242dbb68c39 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 26 Oct 2022 13:19:05 +0200 Subject: [PATCH 5/7] Restrict dereferencing for explicitly decompiled queryables only --- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../Test01NestedExpressions.cs | 4 ++-- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommands.md | 2 +- .../DetailedListOfSupportedCommandsWithSQL.md | 2 +- .../SummaryOfSupportedCommands.md | 2 +- .../NestedExpressionsTests.cs | 18 +++++++++--------- src/DelegateDecompiler/DecompiledQueryable.cs | 2 +- src/DelegateDecompiler/IDecompiledQueryable.cs | 11 +++++++++++ .../OptimizeExpressionVisitor.cs | 10 ++++------ 17 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 src/DelegateDecompiler/IDecompiledQueryable.cs diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 152c3d5c..0ae1403e 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:49 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 7be854a9..c9ef176d 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:49 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 69919226..609564ef 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:33 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:49 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs index 2e5c97ab..814b4f0e 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs @@ -81,7 +81,7 @@ public void TestSubqueryAsVariableReference() //ATTEMPT env.AboutToUseDelegateDecompiler(); - var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus"); + var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus").Decompile(); var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); @@ -105,7 +105,7 @@ public void TestFilterWithSubqueryReference() //ATTEMPT env.AboutToUseDelegateDecompiler(); - var referencedQuery = env.Db.EfParents.Where(p => p.CountChildren == 0); + var referencedQuery = env.Db.EfParents.Where(p => p.CountChildren == 0).Decompile(); var dd = env.Db.EfParents.Decompile().Any(x => referencedQuery.Contains(x)); //VERIFY diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 655606e0..20b9774c 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:41 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index a13d3ec9..6c2c1956 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:41 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 1567f73b..087e996a 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:41 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index da3bfdfc..b739a230 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 4ba4cbed..034dbc2d 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 82afbfa5..f8d3c4f3 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore3.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index da3bfdfc..b739a230 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index d6bc36f0..524a61bd 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index 82afbfa5..f8d3c4f3 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.32.1.0 on Tuesday, 25 October 2022 13:32 +## Documentation produced for DelegateDecompiler, version 0.33.0.0 on Wednesday, 26 October 2022 12:42 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). diff --git a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs index 4f922b7e..7a533fb0 100644 --- a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs +++ b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs @@ -15,8 +15,8 @@ public class NestedExpressionsTests : DecompilerTestsBase int M1() => 0; static int M2() => 0; - readonly IQueryable fQref1 = Enumerable.Empty().AsQueryable(); - static IQueryable fQref2 = Enumerable.Empty().AsQueryable(); + readonly IQueryable fQref1 = Enumerable.Empty().AsQueryable().Decompile(); + static IQueryable fQref2 = Enumerable.Empty().AsQueryable().Decompile(); [Decompile] IQueryable pQref1 => Enumerable.Empty().AsQueryable(); [Decompile] @@ -195,30 +195,30 @@ public void TestFuncWithStaticMethodClosure() ); } - [Test] + [Test, Ignore("Difference is expected")] public void TestQueryableBoundAsVariable() { - IQueryable query = Enumerable.Empty().AsQueryable().Where(i => i >= 0); + IQueryable query = Enumerable.Empty().AsQueryable().Where(i => i >= 0).Decompile(); Test, IQueryable>>( - ints => query, + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), ints => query ); } - [Test] + [Test, Ignore("Difference is expected")] public void TestQueryableRefFromField() { Test, IQueryable>>( - ints => fQref1.Where(i => i >= 0), + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), ints => fQref1.Where(i => i >= 0) ); } - [Test] + [Test, Ignore("Difference is expected")] public void TestQueryableRefFromStaticField() { Test, IQueryable>>( - ints => fQref2.Where(i => i >= 0), + ints => Enumerable.Empty().AsQueryable().Where(i => i >= 0), ints => fQref2.Where(i => i >= 0) ); } diff --git a/src/DelegateDecompiler/DecompiledQueryable.cs b/src/DelegateDecompiler/DecompiledQueryable.cs index 6fb33bd5..9a22ba0f 100644 --- a/src/DelegateDecompiler/DecompiledQueryable.cs +++ b/src/DelegateDecompiler/DecompiledQueryable.cs @@ -6,7 +6,7 @@ namespace DelegateDecompiler { - public class DecompiledQueryable : IOrderedQueryable + public class DecompiledQueryable : IDecompiledQueryable, IOrderedQueryable { private readonly IQueryable inner; private readonly IQueryProvider provider; diff --git a/src/DelegateDecompiler/IDecompiledQueryable.cs b/src/DelegateDecompiler/IDecompiledQueryable.cs new file mode 100644 index 00000000..b8967378 --- /dev/null +++ b/src/DelegateDecompiler/IDecompiledQueryable.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DelegateDecompiler +{ + public interface IDecompiledQueryable + { + } +} diff --git a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs index d1b7816f..8f301952 100644 --- a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs +++ b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs @@ -345,13 +345,11 @@ protected override Expression VisitMember(MemberExpression node) { if (typeof(IQueryable).IsAssignableFrom(node.Type)) { - if (Configuration.Instance.ShouldDecompile(node.Member)) + if (!(node.Expression is ParameterExpression) && node.Member is FieldInfo) { - return Visit(node.Decompile()); - } - else if (!(node.Expression is ParameterExpression) && node.Member is FieldInfo) - { - return Visit((node.Evaluate()).Expression.Decompile()); + var referencedQueryable = node.Evaluate(); + if (referencedQueryable is IDecompiledQueryable) + return Visit(referencedQueryable.Expression); } } return base.VisitMember(node); From d6423891d7293c1f4337352f42e7618e5f8fc629 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 17 Nov 2022 09:04:18 +0100 Subject: [PATCH 6/7] Adding tests --- .../Test01NestedExpressions.cs | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs index 814b4f0e..cc694c67 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using DelegateDecompiler.EntityFramework.Tests.EfItems; using DelegateDecompiler.EntityFramework.Tests.EfItems.Abstracts; using DelegateDecompiler.EntityFramework.Tests.Helpers; @@ -74,13 +75,34 @@ public void TestSubqueryAsContextExtensionMethod() #if EF_CORE && !EF_CORE3 && !EF_CORE5 [Ignore("Not natively supported in EF_CORE < 3")] #endif - public void TestSubqueryAsVariableReference() + public void TestFailingSubqueryAsVariableReference() { using (var env = new MethodEnvironment(classEnv)) { //ATTEMPT env.AboutToUseDelegateDecompiler(); + var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus"); + var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); + + //VERIFY + Assert.Throws(() => query.ToList()); + } + } + + [Test] +#if EF_CORE && !EF_CORE3 && !EF_CORE5 + [Ignore("Not natively supported in EF_CORE < 3")] +#endif + public void TestSubqueryAsVariableReference() + { + using (var env = new MethodEnvironment(classEnv)) + { + //SETUP + var linq = env.Db.Set().Where(it => it.Animals.Intersect(env.Db.Set().Where(a => a is Dog)).Any()) + .ToList(); + //ATTEMPT + env.AboutToUseDelegateDecompiler(); var referencedQuery = env.Db.Set().Where(it => it.Species == "Canis lupus").Decompile(); var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); @@ -88,7 +110,7 @@ public void TestSubqueryAsVariableReference() var list = query.ToList(); //VERIFY - Assert.AreEqual(1, list.Count()); + env.CompareAndLogList(linq, list); } } From 41995caeb977ac1111f6f54c6c47b4b37317c154 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 17 Nov 2022 09:25:54 +0100 Subject: [PATCH 7/7] Fix TargetFrameworks different exceptions expected --- .../TestGroup90AdditionalFeatures/Test01NestedExpressions.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs index cc694c67..8a0dfdd9 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup90AdditionalFeatures/Test01NestedExpressions.cs @@ -85,7 +85,11 @@ public void TestFailingSubqueryAsVariableReference() var query = env.Db.Set().Where(it => it.Animals.Intersect(referencedQuery).Any()).Decompile(); //VERIFY +#if EF_CORE + Assert.Throws(() => query.ToList()); +#else Assert.Throws(() => query.ToList()); +#endif } }