1- // Copyright (C) 2003-2010 Xtensive LLC.
2- // All rights reserved .
3- // For conditions of distribution and use, see license .
1+ // Copyright (C) 2009-2020 Xtensive LLC.
2+ // This code is distributed under MIT license terms .
3+ // See the License.txt file in the project root for more information .
44// Created by: Alexis Kochetov
55// Created: 2009.05.05
66
77using System ;
8- using System . Diagnostics ;
98using System . Linq ;
109using System . Collections . Generic ;
1110using System . Linq . Expressions ;
12- using Xtensive . Core ;
1311using Xtensive . Orm . Model ;
1412
1513namespace Xtensive . Orm . Linq . Expressions
@@ -19,94 +17,115 @@ internal class EntityExpression : ParameterizedExpression,
1917 {
2018 private List < PersistentFieldExpression > fields ;
2119
22- public TypeInfo PersistentType { get ; private set ; }
20+ public TypeInfo PersistentType { get ; }
2321
24- public KeyExpression Key { get ; private set ; }
22+ public KeyExpression Key { get ; }
2523
2624 public List < PersistentFieldExpression > Fields
2725 {
28- get { return fields ; }
29- private set
30- {
26+ get => fields ;
27+ private set {
3128 fields = value ;
32- var fieldExpressions = fields . OfType < FieldExpression > ( ) ;
33- foreach ( var fieldExpression in fieldExpressions )
29+ foreach ( var fieldExpression in fields . OfType < FieldExpression > ( ) ) {
3430 fieldExpression . Owner = this ;
31+ }
3532 }
3633 }
3734
3835 public bool IsNullable { get ; set ; }
3936
4037 public Expression Remap ( int offset , Dictionary < Expression , Expression > processedExpressions )
4138 {
42- if ( ! CanRemap )
39+ if ( ! CanRemap ) {
4340 return this ;
44- Expression value ;
45- if ( processedExpressions . TryGetValue ( this , out value ) )
41+ }
42+
43+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
4644 return value ;
45+ }
4746
4847 var keyExpression = ( KeyExpression ) Key . Remap ( offset , processedExpressions ) ;
4948 var result = new EntityExpression ( PersistentType , keyExpression , OuterParameter , DefaultIfEmpty ) ;
5049 processedExpressions . Add ( this , result ) ;
5150 result . IsNullable = IsNullable ;
52- result . Fields = Fields
53- . Select ( f => f . Remap ( offset , processedExpressions ) )
54- . Cast < PersistentFieldExpression > ( )
55- . ToList ( ) ;
51+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
52+ foreach ( var field in fields ) {
53+ // Do not convert to LINQ. We want to avoid a closure creation here.
54+ processedFields . Add ( ( PersistentFieldExpression ) field . Remap ( offset , processedExpressions ) ) ;
55+ }
56+
57+ result . Fields = processedFields ;
5658 return result ;
5759 }
5860
5961 public Expression Remap ( int [ ] map , Dictionary < Expression , Expression > processedExpressions )
6062 {
61- if ( ! CanRemap )
63+ if ( ! CanRemap ) {
6264 return this ;
63- Expression value ;
64- if ( processedExpressions . TryGetValue ( this , out value ) )
65+ }
66+
67+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
6568 return value ;
69+ }
6670
6771 var keyExpression = ( KeyExpression ) Key . Remap ( map , processedExpressions ) ;
68- if ( keyExpression == null )
72+ if ( keyExpression == null ) {
6973 return null ;
74+ }
75+
7076 var result = new EntityExpression ( PersistentType , keyExpression , OuterParameter , DefaultIfEmpty ) ;
7177 processedExpressions . Add ( this , result ) ;
7278 result . IsNullable = IsNullable ;
73- result . Fields = Fields
74- . Select ( f => f . Remap ( map , processedExpressions ) )
75- . Where ( f => f != null )
76- . Cast < PersistentFieldExpression > ( )
77- . ToList ( ) ;
79+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
80+ foreach ( var field in fields ) {
81+ // Do not convert to LINQ. We want to avoid a closure creation here.
82+ var mappedField = ( PersistentFieldExpression ) field . Remap ( map , processedExpressions ) ;
83+ if ( mappedField == null ) {
84+ continue ;
85+ }
86+
87+ processedFields . Add ( mappedField ) ;
88+ }
89+
90+ result . Fields = processedFields ;
7891 return result ;
7992 }
8093
8194 public Expression BindParameter ( ParameterExpression parameter , Dictionary < Expression , Expression > processedExpressions )
8295 {
83- Expression value ;
84- if ( processedExpressions . TryGetValue ( this , out value ) )
96+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
8597 return value ;
98+ }
8699
87100 var keyExpression = ( KeyExpression ) Key . BindParameter ( parameter , processedExpressions ) ;
88101 var result = new EntityExpression ( PersistentType , keyExpression , parameter , DefaultIfEmpty ) ;
89102 processedExpressions . Add ( this , result ) ;
90- result . Fields = Fields
91- . Select ( f => f . BindParameter ( parameter , processedExpressions ) )
92- . Cast < PersistentFieldExpression > ( )
93- . ToList ( ) ;
103+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
104+ foreach ( var field in fields ) {
105+ // Do not convert to LINQ. We want to avoid a closure creation here.
106+ processedFields . Add ( ( PersistentFieldExpression ) field . BindParameter ( parameter , processedExpressions ) ) ;
107+ }
108+
109+ result . Fields = processedFields ;
94110 return result ;
95111 }
96112
97113 public Expression RemoveOuterParameter ( Dictionary < Expression , Expression > processedExpressions )
98114 {
99- Expression value ;
100- if ( processedExpressions . TryGetValue ( this , out value ) )
115+ if ( processedExpressions . TryGetValue ( this , out var value ) ) {
101116 return value ;
117+ }
102118
103119 var keyExpression = ( KeyExpression ) Key . RemoveOuterParameter ( processedExpressions ) ;
104120 var result = new EntityExpression ( PersistentType , keyExpression , null , DefaultIfEmpty ) ;
105121 processedExpressions . Add ( this , result ) ;
106- result . Fields = Fields
107- . Select ( f => f . RemoveOuterParameter ( processedExpressions ) )
108- . Cast < PersistentFieldExpression > ( )
109- . ToList ( ) ;
122+ var processedFields = new List < PersistentFieldExpression > ( fields . Count ) ;
123+ foreach ( var field in fields ) {
124+ // Do not convert to LINQ. We want to avoid a closure creation here.
125+ processedFields . Add ( ( PersistentFieldExpression ) field . RemoveOuterParameter ( processedExpressions ) ) ;
126+ }
127+
128+ result . Fields = processedFields ;
110129 return result ;
111130 }
112131
@@ -118,70 +137,88 @@ public static void Fill(EntityExpression entityExpression, int offset)
118137 var typeInfo = entityExpression . PersistentType ;
119138 foreach ( var nestedField in typeInfo . Fields . Except ( entityExpression . Fields . OfType < FieldExpression > ( ) . Select ( field=> field . Field ) ) ) {
120139 var nestedFieldExpression = BuildNestedFieldExpression ( nestedField , offset ) ;
121- var fieldExpression = nestedFieldExpression as FieldExpression ;
122- if ( fieldExpression != null )
140+ if ( nestedFieldExpression is FieldExpression fieldExpression ) {
123141 fieldExpression . Owner = entityExpression ;
142+ }
143+
124144 entityExpression . fields . Add ( nestedFieldExpression ) ;
125145 }
126146 }
127147
128148 public static EntityExpression Create ( TypeInfo typeInfo , int offset , bool keyFieldsOnly )
129149 {
130- if ( ! typeInfo . IsEntity && ! typeInfo . IsInterface )
131- throw new ArgumentException ( string . Format ( Strings . ExPersistentTypeXIsNotEntityOrPersistentInterface , typeInfo . Name ) , "typeInfo" ) ;
132- var fields = new List < PersistentFieldExpression > ( ) ;
150+ if ( ! typeInfo . IsEntity && ! typeInfo . IsInterface ) {
151+ throw new ArgumentException (
152+ string . Format ( Strings . ExPersistentTypeXIsNotEntityOrPersistentInterface , typeInfo . Name ) , nameof ( typeInfo ) ) ;
153+ }
154+
133155 var keyExpression = KeyExpression . Create ( typeInfo , offset ) ;
134- fields . Add ( keyExpression ) ;
156+
157+ List < PersistentFieldExpression > fields ;
135158 var result = new EntityExpression ( typeInfo , keyExpression , null , false ) ;
136159 if ( keyFieldsOnly ) {
160+ fields = new List < PersistentFieldExpression > ( keyExpression . KeyFields . Count + 1 ) { keyExpression } ;
137161 // Add key fields to field collection
138- var keyFieldClones = keyExpression
139- . KeyFields
140- . Select ( kf=> FieldExpression . CreateField ( kf . Field , offset ) )
141- . Cast < PersistentFieldExpression > ( ) ;
142- fields . AddRange ( keyFieldClones ) ;
143- }
144- else
145- foreach ( var nestedField in typeInfo . Fields )
162+ foreach ( var keyField in keyExpression . KeyFields ) {
163+ // Do not convert to LINQ. We want to avoid a closure creation here.
164+ fields . Add ( FieldExpression . CreateField ( keyField . Field , offset ) ) ;
165+ }
166+ }
167+ else {
168+ fields = new List < PersistentFieldExpression > ( typeInfo . Fields . Count + 1 ) { keyExpression } ;
169+ foreach ( var nestedField in typeInfo . Fields ) {
170+ // Do not convert to LINQ. We want to avoid a closure creation here.
146171 fields . Add ( BuildNestedFieldExpression ( nestedField , offset ) ) ;
172+ }
173+ }
174+
147175 result . Fields = fields ;
148176 return result ;
149177 }
150178
151179 public static EntityExpression Create ( EntityFieldExpression entityFieldExpression , int offset )
152180 {
153181 var typeInfo = entityFieldExpression . PersistentType ;
154- var fields = new List < PersistentFieldExpression > ( ) ;
155182 var keyExpression = KeyExpression . Create ( typeInfo , offset ) ;
156- fields . Add ( keyExpression ) ;
157- foreach ( var nestedField in typeInfo . Fields )
158- fields . Add ( BuildNestedFieldExpression ( nestedField , offset ) ) ;
183+ var fields = new List < PersistentFieldExpression > ( typeInfo . Fields . Count + 1 ) { keyExpression } ;
184+ foreach ( var nestedField in typeInfo . Fields ) {
185+ // Do not convert to LINQ. We want to avoid a closure creation here.
186+ fields . Add ( BuildNestedFieldExpression ( nestedField , offset ) ) ;
187+ }
188+
159189 var result = new EntityExpression ( typeInfo , keyExpression , null , entityFieldExpression . DefaultIfEmpty ) {
160190 Fields = fields
161191 } ;
162- if ( entityFieldExpression . OuterParameter == null )
192+ if ( entityFieldExpression . OuterParameter == null ) {
163193 return result ;
164- return ( EntityExpression ) result . BindParameter ( entityFieldExpression . OuterParameter , new Dictionary < Expression , Expression > ( ) ) ;
194+ }
195+
196+ return ( EntityExpression ) result . BindParameter (
197+ entityFieldExpression . OuterParameter , new Dictionary < Expression , Expression > ( ) ) ;
165198 }
166199
167200 private static PersistentFieldExpression BuildNestedFieldExpression ( FieldInfo nestedField , int offset )
168201 {
169- if ( nestedField . IsPrimitive )
202+ if ( nestedField . IsPrimitive ) {
170203 return FieldExpression . CreateField ( nestedField , offset ) ;
171- if ( nestedField . IsStructure )
204+ }
205+
206+ if ( nestedField . IsStructure ) {
172207 return StructureFieldExpression . CreateStructure ( nestedField , offset ) ;
173- if ( nestedField . IsEntity )
208+ }
209+
210+ if ( nestedField . IsEntity ) {
174211 return EntityFieldExpression . CreateEntityField ( nestedField , offset ) ;
175- if ( nestedField . IsEntitySet )
176- return EntitySetExpression . CreateEntitySet ( nestedField ) ;
177- throw new NotSupportedException ( string . Format ( Strings . ExNestedFieldXIsNotSupported , nestedField . Attributes ) ) ;
178- }
212+ }
179213
180- public override string ToString ( )
181- {
182- return string . Format ( "{0} {1}" , base . ToString ( ) , PersistentType . Name ) ;
214+ if ( nestedField . IsEntitySet ) {
215+ return EntitySetExpression . CreateEntitySet ( nestedField ) ;
216+ }
217+
218+ throw new NotSupportedException ( string . Format ( Strings . ExNestedFieldXIsNotSupported , nestedField . Attributes ) ) ;
183219 }
184220
221+ public override string ToString ( ) => $ "{ base . ToString ( ) } { PersistentType . Name } ";
185222
186223 // Constructors
187224
0 commit comments