77using System ;
88using System . Collections . Generic ;
99using System . Linq . Expressions ;
10- using Xtensive . Collections ;
1110using Xtensive . Core ;
1211using Xtensive . Orm . Model ;
1312using System . Linq ;
1413
15-
1614namespace Xtensive . Orm . Linq . Expressions
1715{
1816 internal sealed class StructureFieldExpression : FieldExpression ,
1917 IPersistentExpression
2018 {
2119 private List < PersistentFieldExpression > fields ;
22- public TypeInfo PersistentType { get ; private set ; }
20+ public TypeInfo PersistentType { get ; }
2321
24- public bool IsNullable
25- {
26- get { return Owner != null && Owner . IsNullable ; }
27- }
22+ public bool IsNullable => Owner != null && Owner . IsNullable ;
2823
2924 public List < PersistentFieldExpression > Fields
3025 {
31- get { return fields ; }
32- private set
33- {
26+ get => fields ;
27+ private set {
3428 fields = value ;
35- foreach ( var fieldExpression in fields . OfType < FieldExpression > ( ) )
29+ foreach ( var fieldExpression in fields . OfType < FieldExpression > ( ) ) {
3630 fieldExpression . Owner = this ;
31+ }
3732 }
3833 }
3934
4035 public override Expression Remap ( int offset , Dictionary < Expression , Expression > processedExpressions )
4136 {
42- if ( ! CanRemap )
37+ if ( ! CanRemap ) {
4338 return this ;
39+ }
4440
45- Expression value ;
46- if ( processedExpressions . TryGetValue ( this , out value ) )
41+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
4742 return value ;
43+ }
4844
4945 var newMapping = new Segment < int > ( Mapping . Offset + offset , Mapping . Length ) ;
5046 var result = new StructureFieldExpression ( PersistentType , Field , newMapping , OuterParameter , DefaultIfEmpty ) ;
5147 processedExpressions . Add ( this , result ) ;
52- var processedFields = Fields
53- . Select ( f => f . Remap ( offset , processedExpressions ) )
54- . Cast < PersistentFieldExpression > ( )
55- . ToList ( ) ;
48+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
49+ foreach ( var field in fields ) {
50+ // Do not convert to LINQ. We want to avoid a closure creation here.
51+ processedFields . Add ( ( PersistentFieldExpression ) field . Remap ( offset , processedExpressions ) ) ;
52+ }
5653 if ( Owner == null ) {
5754 result . fields = processedFields ;
5855 return result ;
@@ -65,27 +62,38 @@ public override Expression Remap(int offset, Dictionary<Expression, Expression>
6562
6663 public override Expression Remap ( int [ ] map , Dictionary < Expression , Expression > processedExpressions )
6764 {
68- if ( ! CanRemap )
65+ if ( ! CanRemap ) {
6966 return this ;
67+ }
7068
71- Expression value ;
72- if ( processedExpressions . TryGetValue ( this , out value ) )
69+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
7370 return value ;
71+ }
7472
75- var result = new StructureFieldExpression ( PersistentType , Field , default ( Segment < int > ) , OuterParameter , DefaultIfEmpty ) ;
73+ var result = new StructureFieldExpression ( PersistentType , Field , default , OuterParameter , DefaultIfEmpty ) ;
7674 processedExpressions . Add ( this , result ) ;
77- var processedFields = Fields
78- . Select ( f => f . Remap ( map , processedExpressions ) )
79- . Where ( f => f != null )
80- . Cast < PersistentFieldExpression > ( )
81- . ToList ( ) ;
75+ var offset = int . MaxValue ;
76+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
77+ foreach ( var field in fields ) {
78+ var mappedField = ( PersistentFieldExpression ) field . Remap ( map , processedExpressions ) ;
79+ if ( mappedField == null ) {
80+ continue ;
81+ }
82+
83+ var mappingOffset = mappedField . Mapping . Offset ;
84+ if ( mappingOffset < offset ) {
85+ offset = mappingOffset ;
86+ }
87+
88+ processedFields . Add ( mappedField ) ;
89+ }
90+
8291 if ( processedFields . Count == 0 ) {
8392 processedExpressions [ this ] = null ;
8493 return null ;
8594 }
86- var length = processedFields . Select ( f => f . Mapping . Offset ) . Distinct ( ) . Count ( ) ;
87- var offset = processedFields . Min ( f => f . Mapping . Offset ) ;
88- result . Mapping = new Segment < int > ( offset , length ) ;
95+
96+ result . Mapping = new Segment < int > ( offset , processedFields . Count ) ;
8997 if ( Owner == null ) {
9098 result . fields = processedFields ;
9199 return result ;
@@ -97,16 +105,18 @@ public override Expression Remap(int[] map, Dictionary<Expression, Expression> p
97105
98106 public override Expression BindParameter ( ParameterExpression parameter , Dictionary < Expression , Expression > processedExpressions )
99107 {
100- Expression value ;
101- if ( processedExpressions . TryGetValue ( this , out value ) )
108+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
102109 return value ;
110+ }
103111
104112 var result = new StructureFieldExpression ( PersistentType , Field , Mapping , OuterParameter , DefaultIfEmpty ) ;
105113 processedExpressions . Add ( this , result ) ;
106- var processedFields = Fields
107- . Select ( f => f . BindParameter ( parameter , processedExpressions ) )
108- . Cast < PersistentFieldExpression > ( )
109- . ToList ( ) ;
114+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
115+ foreach ( var field in fields ) {
116+ // Do not convert to LINQ. We want to avoid a closure creation here.
117+ processedFields . Add ( ( PersistentFieldExpression ) field . BindParameter ( parameter , processedExpressions ) ) ;
118+ }
119+
110120 if ( Owner == null ) {
111121 result . fields = processedFields ;
112122 return result ;
@@ -119,16 +129,18 @@ public override Expression BindParameter(ParameterExpression parameter, Dictiona
119129
120130 public override Expression RemoveOuterParameter ( Dictionary < Expression , Expression > processedExpressions )
121131 {
122- Expression value ;
123- if ( processedExpressions . TryGetValue ( this , out value ) )
132+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
124133 return value ;
134+ }
125135
126136 var result = new StructureFieldExpression ( PersistentType , Field , Mapping , OuterParameter , DefaultIfEmpty ) ;
127137 processedExpressions . Add ( this , result ) ;
128- var processedFields = Fields
129- . Select ( f => f . RemoveOuterParameter ( processedExpressions ) )
130- . Cast < PersistentFieldExpression > ( )
131- . ToList ( ) ;
138+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
139+ foreach ( var field in fields ) {
140+ // Do not convert to LINQ. We want to avoid a closure creation here.
141+ processedFields . Add ( ( PersistentFieldExpression ) field . RemoveOuterParameter ( processedExpressions ) ) ;
142+ }
143+
132144 if ( Owner == null ) {
133145 result . fields = processedFields ;
134146 return result ;
@@ -141,26 +153,35 @@ public override Expression RemoveOuterParameter(Dictionary<Expression, Expressio
141153
142154 public override FieldExpression RemoveOwner ( )
143155 {
144- if ( Owner == null )
156+ if ( Owner == null ) {
145157 return this ;
146- var result = new StructureFieldExpression ( PersistentType , Field , Mapping , OuterParameter , DefaultIfEmpty ) ;
147- result . fields = fields
148- . Cast < FieldExpression > ( )
149- . Select ( f => ( PersistentFieldExpression ) f . RemoveOwner ( ) )
150- . ToList ( ) ;
158+ }
159+
160+ var result = new StructureFieldExpression ( PersistentType , Field , Mapping , OuterParameter , DefaultIfEmpty ) {
161+ fields = new List < PersistentFieldExpression > ( fields . Count )
162+ } ;
163+ foreach ( var field in fields ) {
164+ result . fields . Add ( ( ( FieldExpression ) field ) . RemoveOwner ( ) ) ;
165+ }
151166 return result ;
152167 }
153168
154169 public static StructureFieldExpression CreateStructure ( FieldInfo structureField , int offset )
155170 {
156- if ( ! structureField . IsStructure )
171+ if ( ! structureField . IsStructure ) {
157172 throw new ArgumentException ( string . Format ( Strings . ExFieldIsNotStructure , structureField . Name ) ) ;
173+ }
174+
158175 var persistentType = structureField . ReflectedType . Model . Types [ structureField . ValueType ] ;
159176 var mapping = new Segment < int > ( offset + structureField . MappingInfo . Offset , structureField . MappingInfo . Length ) ;
160177 var result = new StructureFieldExpression ( persistentType , structureField , mapping , null , false ) ;
161- result . Fields = persistentType . Fields
162- . Select ( f => BuildNestedFieldExpression ( f , offset + structureField . MappingInfo . Offset ) )
163- . ToList ( ) ;
178+ var processedFields = new List < PersistentFieldExpression > ( persistentType . Fields . Count ) ;
179+ foreach ( var field in persistentType . Fields ) {
180+ // Do not convert to LINQ. We want to avoid a closure creation here.
181+ processedFields . Add ( BuildNestedFieldExpression ( field , offset + structureField . MappingInfo . Offset ) ) ;
182+ }
183+
184+ result . Fields = processedFields ;
164185 return result ;
165186 }
166187
0 commit comments