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.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs new file mode 100644 index 00000000..d999822c --- /dev/null +++ b/src/DelegateDecompiler.EntityFramework.Tests/TestGroup20Relationship/Test01Include.cs @@ -0,0 +1,47 @@ +// Contributed by @JonPSmith (GitHub) www.thereformedprogrammer.com + +using System.Linq; +using DelegateDecompiler.EntityFramework.Tests.Helpers; +using NUnit.Framework; +using DelegateDecompiler.EntityFramework.Tests.EfItems; +#if EF_CORE +using Microsoft.EntityFrameworkCore; +#else +using System.Data.Entity; +#endif + +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.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) diff --git a/src/DelegateDecompiler/DecompileExpressionVisitor.cs b/src/DelegateDecompiler/DecompileExpressionVisitor.cs index cda1f9e3..92327084 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)