@@ -16,15 +16,14 @@ namespace Xtensive.Orm.Linq.Expressions
1616 internal sealed class EntityFieldExpression : FieldExpression ,
1717 IEntityExpression
1818 {
19- public TypeInfo PersistentType { get ; private set ; }
20- public List < PersistentFieldExpression > Fields { get ; private set ; }
21- public KeyExpression Key { get ; private set ; }
19+ private readonly List < PersistentFieldExpression > fields ;
20+
21+ public TypeInfo PersistentType { get ; }
22+ public List < PersistentFieldExpression > Fields => fields ;
23+ public KeyExpression Key { get ; }
2224 public EntityExpression Entity { get ; private set ; }
2325
24- public bool IsNullable
25- {
26- get { return Owner != null && Owner . IsNullable || Field . IsNullable ; }
27- }
26+ public bool IsNullable => ( Owner != null && Owner . IsNullable ) || Field . IsNullable ;
2827
2928 public void RegisterEntityExpression ( int offset )
3029 {
@@ -34,24 +33,27 @@ public void RegisterEntityExpression(int offset)
3433
3534 public override Expression Remap ( int offset , Dictionary < Expression , Expression > processedExpressions )
3635 {
37- if ( ! CanRemap )
36+ if ( ! CanRemap ) {
3837 return this ;
38+ }
3939
40- Expression result ;
41- if ( processedExpressions . TryGetValue ( this , out result ) )
40+ if ( processedExpressions . TryGetValue ( this , out var result ) ) {
4241 return result ;
42+ }
43+
44+ var newFields = new List < PersistentFieldExpression > ( fields . Count ) ;
45+ foreach ( var field in fields ) {
46+ // Do not convert to LINQ. We want to avoid a closure creation here.
47+ newFields . Add ( ( PersistentFieldExpression ) field . Remap ( offset , processedExpressions ) ) ;
48+ }
4349
44- var fields = Fields
45- . Select ( f => f . Remap ( offset , processedExpressions ) )
46- . Cast < PersistentFieldExpression > ( )
47- . ToList ( ) ;
4850 var keyExpression = ( KeyExpression ) Key . Remap ( offset , processedExpressions ) ;
49- var entity = Entity != null
50- ? ( EntityExpression ) Entity . Remap ( offset , processedExpressions )
51- : null ;
52- result = new EntityFieldExpression ( PersistentType , Field , fields , keyExpression . Mapping , keyExpression , entity , OuterParameter , DefaultIfEmpty ) ;
53- if ( Owner == null )
51+ var entity = ( EntityExpression ) Entity ? . Remap ( offset , processedExpressions ) ;
52+ result = new EntityFieldExpression (
53+ PersistentType , Field , newFields , keyExpression . Mapping , keyExpression , entity , OuterParameter , DefaultIfEmpty ) ;
54+ if ( Owner == null ) {
5455 return result ;
56+ }
5557
5658 processedExpressions . Add ( this , result ) ;
5759 Owner . Remap ( offset , processedExpressions ) ;
@@ -60,57 +62,68 @@ public override Expression Remap(int offset, Dictionary<Expression, Expression>
6062
6163 public override Expression Remap ( int [ ] map , Dictionary < Expression , Expression > processedExpressions )
6264 {
63- if ( ! CanRemap )
65+ if ( ! CanRemap ) {
6466 return this ;
67+ }
6568
66- Expression result ;
67- if ( processedExpressions . TryGetValue ( this , out result ) )
69+ if ( processedExpressions . TryGetValue ( this , out var result ) ) {
6870 return result ;
71+ }
6972
70- List < PersistentFieldExpression > fields ;
73+ var newFields = new List < PersistentFieldExpression > ( fields . Count ) ;
7174 using ( new SkipOwnerCheckScope ( ) ) {
72- fields = Fields
73- . Select ( f => f . Remap ( map , processedExpressions ) )
74- . Where ( f => f != null )
75- . Cast < PersistentFieldExpression > ( )
76- . ToList ( ) ;
75+ foreach ( var field in fields ) {
76+ // Do not convert to LINQ. We want to avoid a closure creation here.
77+ var mappedField = ( PersistentFieldExpression ) field . Remap ( map , processedExpressions ) ;
78+ if ( mappedField == null ) {
79+ continue ;
80+ }
81+
82+ newFields . Add ( mappedField ) ;
83+ }
7784 }
78- if ( fields . Count != Fields . Count ) {
85+
86+ if ( newFields . Count != Fields . Count ) {
7987 processedExpressions . Add ( this , null ) ;
8088 return null ;
8189 }
90+
8291 var keyExpression = ( KeyExpression ) Key . Remap ( map , processedExpressions ) ;
8392 EntityExpression entity ;
84- using ( new SkipOwnerCheckScope ( ) )
85- entity = Entity != null
86- ? ( EntityExpression ) Entity . Remap ( map , processedExpressions )
87- : null ;
88- result = new EntityFieldExpression ( PersistentType , Field , fields , keyExpression . Mapping , keyExpression , entity , OuterParameter , DefaultIfEmpty ) ;
89- if ( Owner == null )
93+ using ( new SkipOwnerCheckScope ( ) ) {
94+ entity = ( EntityExpression ) Entity ? . Remap ( map , processedExpressions ) ;
95+ }
96+
97+ result = new EntityFieldExpression (
98+ PersistentType , Field , newFields , keyExpression . Mapping , keyExpression , entity , OuterParameter , DefaultIfEmpty ) ;
99+ if ( Owner == null ) {
90100 return result ;
101+ }
91102
92103 processedExpressions . Add ( this , result ) ;
93104 Owner . Remap ( map , processedExpressions ) ;
94105 return result ;
95106 }
96107
97- public override Expression BindParameter ( ParameterExpression parameter , Dictionary < Expression , Expression > processedExpressions )
108+ public override Expression BindParameter (
109+ ParameterExpression parameter , Dictionary < Expression , Expression > processedExpressions )
98110 {
99- Expression result ;
100- if ( processedExpressions . TryGetValue ( this , out result ) )
111+ if ( processedExpressions . TryGetValue ( this , out var result ) ) {
101112 return result ;
113+ }
102114
103- var fields = Fields
104- . Select ( f => f . BindParameter ( parameter , processedExpressions ) )
105- . Cast < PersistentFieldExpression > ( )
106- . ToList ( ) ;
115+ var newFields = new List < PersistentFieldExpression > ( fields . Count ) ;
116+ foreach ( var field in fields ) {
117+ // Do not convert to LINQ. We want to avoid a closure creation here.
118+ newFields . Add ( ( PersistentFieldExpression ) field . BindParameter ( parameter , processedExpressions ) ) ;
119+ }
107120 var keyExpression = ( KeyExpression ) Key . BindParameter ( parameter , processedExpressions ) ;
108- var entity = Entity != null
109- ? ( EntityExpression ) Entity . BindParameter ( parameter , processedExpressions )
110- : null ;
111- result = new EntityFieldExpression ( PersistentType , Field , fields , Mapping , keyExpression , entity , parameter , DefaultIfEmpty ) ;
112- if ( Owner == null )
121+ var entity = ( EntityExpression ) Entity ? . BindParameter ( parameter , processedExpressions ) ;
122+ result = new EntityFieldExpression (
123+ PersistentType , Field , newFields , Mapping , keyExpression , entity , parameter , DefaultIfEmpty ) ;
124+ if ( Owner == null ) {
113125 return result ;
126+ }
114127
115128 processedExpressions . Add ( this , result ) ;
116129 Owner . BindParameter ( parameter , processedExpressions ) ;
@@ -119,21 +132,22 @@ public override Expression BindParameter(ParameterExpression parameter, Dictiona
119132
120133 public override Expression RemoveOuterParameter ( Dictionary < Expression , Expression > processedExpressions )
121134 {
122- Expression result ;
123- if ( processedExpressions . TryGetValue ( this , out result ) )
135+ if ( processedExpressions . TryGetValue ( this , out var result ) ) {
124136 return result ;
137+ }
125138
126- var fields = Fields
127- . Select ( f => f . RemoveOuterParameter ( processedExpressions ) )
128- . Cast < PersistentFieldExpression > ( )
129- . ToList ( ) ;
139+ var newFields = new List < PersistentFieldExpression > ( fields . Count ) ;
140+ foreach ( var field in fields ) {
141+ // Do not convert to LINQ. We want to avoid a closure creation here.
142+ newFields . Add ( ( PersistentFieldExpression ) field . RemoveOuterParameter ( processedExpressions ) ) ;
143+ }
130144 var keyExpression = ( KeyExpression ) Key . RemoveOuterParameter ( processedExpressions ) ;
131- var entity = Entity != null
132- ? ( EntityExpression ) Entity . RemoveOuterParameter ( processedExpressions )
133- : null ;
134- result = new EntityFieldExpression ( PersistentType , Field , fields , Mapping , keyExpression , entity , null , DefaultIfEmpty ) ;
135- if ( Owner == null )
145+ var entity = ( EntityExpression ) Entity ? . RemoveOuterParameter ( processedExpressions ) ;
146+ result = new EntityFieldExpression (
147+ PersistentType , Field , newFields , Mapping , keyExpression , entity , null , DefaultIfEmpty ) ;
148+ if ( Owner == null ) {
136149 return result ;
150+ }
137151
138152 processedExpressions . Add ( this , result ) ;
139153 Owner . RemoveOuterParameter ( processedExpressions ) ;
@@ -173,18 +187,18 @@ private static PersistentFieldExpression BuildNestedFieldExpression(FieldInfo ne
173187 // Constructors
174188
175189 private EntityFieldExpression (
176- TypeInfo persistentType ,
177- FieldInfo field ,
190+ TypeInfo persistentType ,
191+ FieldInfo field ,
178192 List < PersistentFieldExpression > fields ,
179193 in Segment < int > mapping ,
180- KeyExpression key ,
181- EntityExpression entity ,
182- ParameterExpression parameterExpression ,
194+ KeyExpression key ,
195+ EntityExpression entity ,
196+ ParameterExpression parameterExpression ,
183197 bool defaultIfEmpty )
184198 : base ( ExtendedExpressionType . EntityField , field , mapping , parameterExpression , defaultIfEmpty )
185199 {
186200 PersistentType = persistentType ;
187- Fields = fields ;
201+ this . fields = fields ;
188202 Key = key ;
189203 Entity = entity ;
190204 }
0 commit comments