@@ -1693,13 +1693,24 @@ protected override Expression VisitExtension(Expression extensionExpression)
1693
1693
{
1694
1694
if ( navigation . IsCollection )
1695
1695
{
1696
- var innerSelectExpression = BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable (
1697
- entityProjectionExpression ,
1698
- targetEntityType . GetViewOrTableMappings ( ) . Single ( ) . Table ,
1699
- navigation ) ;
1696
+ // just need any column - we use it only to extract the table it originated from
1697
+ var sourceColumn = entityProjectionExpression
1698
+ . BindProperty (
1699
+ navigation . IsOnDependent
1700
+ ? foreignKey . Properties [ 0 ]
1701
+ : foreignKey . PrincipalKey . Properties [ 0 ] ) ;
1702
+
1703
+ var sourceTable = FindRootTableExpressionForColumn ( sourceColumn ) ;
1704
+ TableExpressionBase ownedTable = new TableExpression ( targetEntityType . GetViewOrTableMappings ( ) . Single ( ) . Table ) ;
1705
+
1706
+ foreach ( var annotation in sourceTable . GetAnnotations ( ) )
1707
+ {
1708
+ ownedTable = ownedTable . AddAnnotation ( annotation . Name , annotation . Value ) ;
1709
+ }
1700
1710
1701
- var innerShapedQuery = CreateShapedQueryExpression (
1702
- targetEntityType , innerSelectExpression ) ;
1711
+ var innerSelectExpression = new SelectExpression ( targetEntityType , ownedTable ) ;
1712
+
1713
+ var innerShapedQuery = CreateShapedQueryExpression ( targetEntityType , innerSelectExpression ) ;
1703
1714
1704
1715
var makeNullable = foreignKey . PrincipalKey . Properties
1705
1716
. Concat ( foreignKey . Properties )
@@ -1746,102 +1757,9 @@ outerKey is NewArrayExpression newArrayExpression
1746
1757
Expression . Quote ( correlationPredicate ) ) ;
1747
1758
}
1748
1759
1749
- var innerShaper = entityProjectionExpression . BindNavigation ( navigation ) ;
1750
- if ( innerShaper == null )
1751
- {
1752
- // Owned types don't support inheritance See https://github.com/dotnet/efcore/issues/9630
1753
- // So there is no handling for dependent having TPT/TPC
1754
- // If navigation is defined on derived type and entity type is part of TPT then we need to get ITableBase for derived type.
1755
- // TODO: The following code should also handle Function and SqlQuery mappings
1756
- var table = navigation . DeclaringEntityType . BaseType == null
1757
- || entityType . FindDiscriminatorProperty ( ) != null
1758
- ? navigation . DeclaringEntityType . GetViewOrTableMappings ( ) . Single ( ) . Table
1759
- : navigation . DeclaringEntityType . GetViewOrTableMappings ( ) . Select ( tm => tm . Table )
1760
- . Except ( navigation . DeclaringEntityType . BaseType . GetViewOrTableMappings ( ) . Select ( tm => tm . Table ) )
1761
- . Single ( ) ;
1762
- if ( table . GetReferencingRowInternalForeignKeys ( foreignKey . PrincipalEntityType ) . Contains ( foreignKey ) )
1763
- {
1764
- // Mapped to same table
1765
- // We get identifying column to figure out tableExpression to pull columns from and nullability of most principal side
1766
- var identifyingColumn = entityProjectionExpression . BindProperty ( entityType . FindPrimaryKey ( ) ! . Properties . First ( ) ) ;
1767
- var principalNullable = identifyingColumn . IsNullable
1768
- // Also make nullable if navigation is on derived type and and principal is TPT
1769
- // Since identifying PK would be non-nullable but principal can still be null
1770
- // Derived owned navigation does not de-dupe the PK column which for principal is from base table
1771
- // and for dependent on derived table
1772
- || ( entityType . FindDiscriminatorProperty ( ) == null
1773
- && navigation . DeclaringEntityType . IsStrictlyDerivedFrom ( entityShaperExpression . EntityType ) ) ;
1774
-
1775
- var entityProjection = _selectExpression . GenerateWeakEntityProjectionExpression (
1776
- targetEntityType , table , identifyingColumn . Name , identifyingColumn . Table , principalNullable ) ;
1777
-
1778
- if ( entityProjection != null )
1779
- {
1780
- innerShaper = new RelationalEntityShaperExpression ( targetEntityType , entityProjection , principalNullable ) ;
1781
- }
1782
- }
1783
-
1784
- if ( innerShaper == null )
1785
- {
1786
- // InnerShaper is still null if either it is not table sharing or we failed to find table to pick data from
1787
- // So we find the table it is mapped to and generate join with it.
1788
- // Owned types don't support inheritance See https://github.com/dotnet/efcore/issues/9630
1789
- // So there is no handling for dependent having TPT
1790
- table = targetEntityType . GetViewOrTableMappings ( ) . Single ( ) . Table ;
1791
- var innerSelectExpression = BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable (
1792
- entityProjectionExpression ,
1793
- table ,
1794
- navigation ) ;
1795
-
1796
- var innerShapedQuery = CreateShapedQueryExpression ( targetEntityType , innerSelectExpression ) ;
1797
-
1798
- var makeNullable = foreignKey . PrincipalKey . Properties
1799
- . Concat ( foreignKey . Properties )
1800
- . Select ( p => p . ClrType )
1801
- . Any ( t => t . IsNullableType ( ) ) ;
1802
-
1803
- var outerKey = entityShaperExpression . CreateKeyValuesExpression (
1804
- navigation . IsOnDependent
1805
- ? foreignKey . Properties
1806
- : foreignKey . PrincipalKey . Properties ,
1807
- makeNullable ) ;
1808
- var innerKey = innerShapedQuery . ShaperExpression . CreateKeyValuesExpression (
1809
- navigation . IsOnDependent
1810
- ? foreignKey . PrincipalKey . Properties
1811
- : foreignKey . Properties ,
1812
- makeNullable ) ;
1813
-
1814
- var joinPredicate = _sqlTranslator . Translate (
1815
- Infrastructure . ExpressionExtensions . CreateEqualsExpression ( outerKey , innerKey ) ) ! ;
1816
- // Following conditions should match conditions for pushdown on outer during SelectExpression.AddJoin method
1817
- var pushdownRequired = _selectExpression . Limit != null
1818
- || _selectExpression . Offset != null
1819
- || _selectExpression . IsDistinct
1820
- || _selectExpression . GroupBy . Count > 0 ;
1821
- _selectExpression . AddLeftJoin ( innerSelectExpression , joinPredicate ) ;
1822
-
1823
- // If pushdown was required on SelectExpression then we need to fetch the updated entity projection
1824
- if ( pushdownRequired )
1825
- {
1826
- if ( doee is not null )
1827
- {
1828
- entityShaperExpression = _deferredOwnedExpansionRemover . UnwrapDeferredEntityProjectionExpression ( doee ) ;
1829
- }
1830
-
1831
- entityProjectionExpression = GetEntityProjectionExpression ( entityShaperExpression ) ;
1832
- }
1833
-
1834
- var leftJoinTable = _selectExpression . Tables . Last ( ) ;
1835
-
1836
- innerShaper = new RelationalEntityShaperExpression (
1837
- targetEntityType ,
1838
- _selectExpression . GenerateWeakEntityProjectionExpression (
1839
- targetEntityType , table , null , leftJoinTable , nullable : true ) ! ,
1840
- nullable : true ) ;
1841
- }
1842
-
1843
- entityProjectionExpression . AddNavigationBinding ( navigation , innerShaper ) ;
1844
- }
1760
+ var innerShaper = entityProjectionExpression . BindNavigation ( navigation )
1761
+ ?? _selectExpression . GenerateOwnedReferenceEntityProjectionExpression (
1762
+ entityProjectionExpression , navigation , _sqlExpressionFactory ) ;
1845
1763
}
1846
1764
1847
1765
return doee is not null
@@ -1851,29 +1769,6 @@ outerKey is NewArrayExpression newArrayExpression
1851
1769
( ProjectionBindingExpression ) entityShaperExpression . ValueBufferExpression ,
1852
1770
navigation ) ;
1853
1771
1854
- SelectExpression BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable (
1855
- EntityProjectionExpression entityProjectionExpression ,
1856
- ITableBase targetTable ,
1857
- INavigation navigation )
1858
- {
1859
- // just need any column - we use it only to extract the table it originated from
1860
- var sourceColumn = entityProjectionExpression
1861
- . BindProperty (
1862
- navigation . IsOnDependent
1863
- ? foreignKey . Properties [ 0 ]
1864
- : foreignKey . PrincipalKey . Properties [ 0 ] ) ;
1865
-
1866
- var sourceTable = FindRootTableExpressionForColumn ( sourceColumn ) ;
1867
- TableExpressionBase ownedTable = new TableExpression ( targetTable ) ;
1868
-
1869
- foreach ( var annotation in sourceTable . GetAnnotations ( ) )
1870
- {
1871
- ownedTable = ownedTable . AddAnnotation ( annotation . Name , annotation . Value ) ;
1872
- }
1873
-
1874
- return _sqlExpressionFactory . Select ( targetEntityType , ownedTable ) ;
1875
- }
1876
-
1877
1772
static TableExpressionBase FindRootTableExpressionForColumn ( ColumnExpression column )
1878
1773
{
1879
1774
var table = column . Table ;
0 commit comments