From 4ce1803e5a50cb0038e2933ea6e36e91b84aceb3 Mon Sep 17 00:00:00 2001 From: "Pavel.Mayorov" Date: Tue, 9 Jun 2015 13:38:55 +0500 Subject: [PATCH 1/4] Resolved Compute - Include - Decompile problem --- .../DecompileExpressionVisitor.cs | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/DelegateDecompiler/DecompileExpressionVisitor.cs b/src/DelegateDecompiler/DecompileExpressionVisitor.cs index cda1f9e3..58d955ab 100644 --- a/src/DelegateDecompiler/DecompileExpressionVisitor.cs +++ b/src/DelegateDecompiler/DecompileExpressionVisitor.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -12,6 +12,50 @@ public static Expression Decompile(Expression expression) return new DecompileExpressionVisitor().Visit(expression); } + private static readonly object NULL = new object(); // for use as a dictionary key + private readonly Dictionary visitedConstants; + + private bool hasAnyChanges = false; + public override Expression Visit(Expression node) + { + var result = base.Visit(node); + if (result != node) + hasAnyChanges = true; + return result; + } + + private DecompileExpressionVisitor(Dictionary sharedVisitedConstants = null) + { + this.visitedConstants = sharedVisitedConstants ?? new Dictionary(); + } + + protected override Expression VisitConstant(ConstantExpression node) + { + Expression result; + if (visitedConstants.TryGetValue(node.Value ?? NULL, out result)) + { + return result; // avoid infinite recursion + } + + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + visitedConstants.Add(node.Value ?? NULL, node); + + var value = (IQueryable)node.Value; + var childVisitor = new DecompileExpressionVisitor(visitedConstants); + result = childVisitor.Visit(value.Expression); + + if (childVisitor.hasAnyChanges) + { + result = Expression.Constant(value.Provider.CreateQuery(result), node.Type); + visitedConstants[node.Value ?? NULL] = result; + return result; + } + } + + return node; + } + protected override Expression VisitMember(MemberExpression node) { if (ShouldDecompile(node.Member) && node.Member is PropertyInfo property) From 286044a0249ecd9a55b2fd76fbd89696d8814c74 Mon Sep 17 00:00:00 2001 From: txavier Date: Mon, 6 Nov 2017 11:35:20 +1300 Subject: [PATCH 2/4] Unit test and fixes from #53 --- .../TestGroup20Relationship/Test01Include.cs | 44 ++++++++++ .../DecompileExpressionVisitor.cs | 86 +++++++++---------- 2 files changed, 87 insertions(+), 43 deletions(-) create mode 100644 src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs new file mode 100644 index 00000000..ffe2a995 --- /dev/null +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs @@ -0,0 +1,44 @@ +// Contributed by @JonPSmith (GitHub) www.thereformedprogrammer.com + +using System.Linq; +using DelegateDecompiler.EntityFramework.Tests.Helpers; +using NUnit.Framework; +using DelegateDecompiler.EntityFramework.Tests.EfItems; +using System.Data.Entity; +using System.Collections.Generic; + +namespace DelegateDecompiler.EntityFramework.Tests.TestGroup05BasicFeatures +{ + class Test01Include + { + private ClassEnvironment classEnv; + + [OneTimeSetUp] + public void SetUpFixture() + { + classEnv = new ClassEnvironment(); + } + + [Computed] + private static bool ComputedSample() { return true; } + + [Test] + public void TestInclude() + { + using (var db = new EfTestDbContext()) + using (var env = new MethodEnvironment(classEnv)) + { + //SETUP + var linq = db.EfParents.Where(p => true).Include(p => p.Children).ToList(); + + //ATTEMPT + env.AboutToUseDelegateDecompiler(); + var dd = env.Db.EfParents.Where(p => ComputedSample()).Include(p => p.Children).Decompile().ToList(); + + //VERIFY + env.CompareAndLogList(linq, dd); + } + } + + } +} diff --git a/src/DelegateDecompiler/DecompileExpressionVisitor.cs b/src/DelegateDecompiler/DecompileExpressionVisitor.cs index 58d955ab..92327084 100644 --- a/src/DelegateDecompiler/DecompileExpressionVisitor.cs +++ b/src/DelegateDecompiler/DecompileExpressionVisitor.cs @@ -12,50 +12,50 @@ public static Expression Decompile(Expression expression) return new DecompileExpressionVisitor().Visit(expression); } - private static readonly object NULL = new object(); // for use as a dictionary key - private readonly Dictionary visitedConstants; - - private bool hasAnyChanges = false; - public override Expression Visit(Expression node) - { - var result = base.Visit(node); - if (result != node) - hasAnyChanges = true; - return result; - } - - private DecompileExpressionVisitor(Dictionary sharedVisitedConstants = null) - { - this.visitedConstants = sharedVisitedConstants ?? new Dictionary(); - } - - protected override Expression VisitConstant(ConstantExpression node) - { - Expression result; - if (visitedConstants.TryGetValue(node.Value ?? NULL, out result)) - { - return result; // avoid infinite recursion - } - - if (typeof(IQueryable).IsAssignableFrom(node.Type)) - { - visitedConstants.Add(node.Value ?? NULL, node); - - var value = (IQueryable)node.Value; - var childVisitor = new DecompileExpressionVisitor(visitedConstants); - result = childVisitor.Visit(value.Expression); - - if (childVisitor.hasAnyChanges) - { - result = Expression.Constant(value.Provider.CreateQuery(result), node.Type); - visitedConstants[node.Value ?? NULL] = result; - return result; - } - } - - return node; - } + private static readonly object NULL = new object(); // for use as a dictionary key + private readonly Dictionary visitedConstants; + private bool hasAnyChanges = false; + public override Expression Visit(Expression node) + { + var result = base.Visit(node); + if (result != node) + hasAnyChanges = true; + return result; + } + + private DecompileExpressionVisitor(Dictionary sharedVisitedConstants = null) + { + this.visitedConstants = sharedVisitedConstants ?? new Dictionary(); + } + + protected override Expression VisitConstant(ConstantExpression node) + { + Expression result; + if (visitedConstants.TryGetValue(node.Value ?? NULL, out result)) + { + return result; // avoid infinite recursion + } + + if (typeof(IQueryable).IsAssignableFrom(node.Type)) + { + visitedConstants.Add(node.Value ?? NULL, node); + + var value = (IQueryable)node.Value; + var childVisitor = new DecompileExpressionVisitor(visitedConstants); + result = childVisitor.Visit(value.Expression); + + if (childVisitor.hasAnyChanges) + { + result = Expression.Constant(value.Provider.CreateQuery(result), node.Type); + visitedConstants[node.Value ?? NULL] = result; + return result; + } + } + + return node; + } + protected override Expression VisitMember(MemberExpression node) { if (ShouldDecompile(node.Member) && node.Member is PropertyInfo property) From 9fc4d1719be69f6fd5f47a839be1ee9f7d3cb9c6 Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Sun, 5 May 2024 23:34:39 +1000 Subject: [PATCH 3/4] Update unit test --- .../TestGroup20Relationship/Test01Include.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs index ffe2a995..d999822c 100644 --- a/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs @@ -4,8 +4,11 @@ using DelegateDecompiler.EntityFramework.Tests.Helpers; using NUnit.Framework; using DelegateDecompiler.EntityFramework.Tests.EfItems; +#if EF_CORE +using Microsoft.EntityFrameworkCore; +#else using System.Data.Entity; -using System.Collections.Generic; +#endif namespace DelegateDecompiler.EntityFramework.Tests.TestGroup05BasicFeatures { From 943ba62b3869af1da7795d4fa858701b629f6013 Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Sun, 5 May 2024 23:47:07 +1000 Subject: [PATCH 4/4] Re-run tests --- .../DetailedListOfSupportedCommands.md | 8 +++++++- .../DetailedListOfSupportedCommandsWithSQL.md | 8 +++++++- .../GeneratedDocumentation/SummaryOfSupportedCommands.md | 6 +++++- .../DetailedListOfSupportedCommands.md | 8 +++++++- .../DetailedListOfSupportedCommandsWithSQL.md | 8 +++++++- .../GeneratedDocumentation/SummaryOfSupportedCommands.md | 6 +++++- .../DetailedListOfSupportedCommands.md | 8 +++++++- .../DetailedListOfSupportedCommandsWithSQL.md | 8 +++++++- .../GeneratedDocumentation/SummaryOfSupportedCommands.md | 6 +++++- 9 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index 683a6170..c565a25d 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 9933161b..d468a368 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFramework.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index dbec4c5c..ce89c072 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework v6.1](http://msdn.microsoft.com/en-us/data/aa937723) (EF). @@ -22,6 +22,10 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +- **Not Supported** + * [Include](../TestGroup20Relationship/Test01Include.cs) (1 tests) + ### Group: Basic Features - Supported * [Select](../TestGroup05BasicFeatures/Test01Select.cs) (8 tests) diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index f7328816..730b758b 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index 636f860e..ea7276c2 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore6.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index dba07102..b0b39e61 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.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,10 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +- **Not Supported** + * [Include](../TestGroup20Relationship/Test01Include.cs) (1 tests) + ### Group: Basic Features - Supported * [Select](../TestGroup05BasicFeatures/Test01Select.cs) (10 tests) diff --git a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md index f7328816..730b758b 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommands.md @@ -1,6 +1,6 @@ Detail of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md index e8699d42..be3511a7 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md +++ b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/DetailedListOfSupportedCommandsWithSQL.md @@ -1,6 +1,6 @@ Detail With Sql of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,12 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +#### [Include](../TestGroup20Relationship/Test01Include.cs): +- **Not Supported** + * Include (line 42) + + ### Group: Basic Features #### [Select](../TestGroup05BasicFeatures/Test01Select.cs): - Supported diff --git a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md index dba07102..b0b39e61 100644 --- a/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md +++ b/src/DelegateDecompiler.EntityFrameworkCore8.Tests/GeneratedDocumentation/SummaryOfSupportedCommands.md @@ -1,6 +1,6 @@ Summary of supported commands ============ -## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:15 +## Documentation produced for DelegateDecompiler, version 0.34.0.0 on Sunday, 05 May 2024 23:45 This file documents what linq commands **DelegateDecompiler** supports when working with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF). @@ -22,6 +22,10 @@ That will make it much easier to diagnose your issue. More will appear as we move forward.* +### Group: Relationship +- **Not Supported** + * [Include](../TestGroup20Relationship/Test01Include.cs) (1 tests) + ### Group: Basic Features - Supported * [Select](../TestGroup05BasicFeatures/Test01Select.cs) (10 tests)