File: ColumnMapProcessor.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (555 lines) | stat: -rw-r--r-- 24,829 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
//---------------------------------------------------------------------
// <copyright file="ColumnMapProcessor.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Common.Utils;
using md = System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
using System.Data.Query.PlanCompiler;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
using System.Globalization;

namespace System.Data.Query.PlanCompiler
{

    internal class ColumnMapProcessor
    {

        #region "public" methods

        internal ColumnMap ExpandColumnMap()
        {
            // special handling for the case when the top-level var is a collection. 
            // The element type of the collection may have changed, and consequently a new
            // var will have been created. We simply create a columnmap with that var.
            if (m_varInfo.Kind == VarInfoKind.CollectionVarInfo)
            {
                return new VarRefColumnMap(m_columnMap.Var.Type, m_columnMap.Name, ((CollectionVarInfo)m_varInfo).NewVar);
            }
            else if(m_varInfo.Kind == VarInfoKind.PrimitiveTypeVarInfo)
            {
                return new VarRefColumnMap(m_columnMap.Var.Type, m_columnMap.Name, ((PrimitiveTypeVarInfo)m_varInfo).NewVar);
            }
            else
            {
                return this.CreateColumnMap(m_columnMap.Var.Type, m_columnMap.Name);
            }
        }

        #endregion

        #region Constructors

        internal ColumnMapProcessor(VarRefColumnMap columnMap, VarInfo varInfo, StructuredTypeInfo typeInfo)
        {
            m_columnMap = columnMap;
            m_varInfo = varInfo;
            PlanCompiler.Assert(varInfo.NewVars != null && varInfo.NewVars.Count > 0, "No new Vars specified");
            m_varList = varInfo.NewVars.GetEnumerator();
            m_typeInfo = typeInfo;
        }

        #endregion

        #region private state

        private IEnumerator<Var> m_varList;
        private VarInfo m_varInfo;
        private VarRefColumnMap m_columnMap;
        private StructuredTypeInfo m_typeInfo;
        private const string c_TypeIdColumnName = "__TypeId"; // name of the typeid column
        private const string c_EntitySetIdColumnName = "__EntitySetId"; // name of the entityset column
        private const string c_NullSentinelColumnName = "__NullSentinel"; // name of the nullability column

        #endregion

        #region private methods

        private Var GetNextVar()
        {
            if (m_varList.MoveNext())
            {
                return m_varList.Current;
            }
            PlanCompiler.Assert(false, "Could not GetNextVar");
            return null;
        }

        /// <summary>
        /// Creates a column map for a column
        /// </summary>
        /// <param name="type">column datatype</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private ColumnMap CreateColumnMap(md.TypeUsage type, string name)
        {
            // For simple types, create a simple column map
            // Temporarily, handle collections exactly the same way
            if (!TypeUtils.IsStructuredType(type))
            {
                return CreateSimpleColumnMap(type, name);
            }

            // At this point, we must be dealing with either a record type, a 
            // complex type, or an entity type
            return CreateStructuralColumnMap(type, name);
        }

        /// <summary>
        /// Create a column map for a complextype column
        /// </summary>
        /// <param name="typeInfo">Type information for the type</param>
        /// <param name="name">column name</param>
        /// <param name="superTypeColumnMap">Supertype info if any</param>
        /// <param name="discriminatorMap">Dictionary of typeidvalue->column map</param>
        /// <param name="allMaps">List of all maps</param>
        /// <returns></returns>
        private ComplexTypeColumnMap CreateComplexTypeColumnMap(TypeInfo typeInfo, string name, ComplexTypeColumnMap superTypeColumnMap,
            Dictionary<object, TypedColumnMap> discriminatorMap, List<TypedColumnMap> allMaps)
        {
            List<ColumnMap> propertyColumnMapList = new List<ColumnMap>();
            IEnumerable myProperties = null;

            SimpleColumnMap nullSentinelColumnMap = null;
            if (typeInfo.HasNullSentinelProperty)
            {
                nullSentinelColumnMap = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(typeInfo.NullSentinelProperty), c_NullSentinelColumnName);
            }

            // Copy over information from my supertype if it already exists
            if (superTypeColumnMap != null)
            {
                foreach (ColumnMap c in superTypeColumnMap.Properties)
                {
                    propertyColumnMapList.Add(c);
                }
                myProperties = TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type);
            }
            else
            {
                // need to get all members otherwise
                myProperties = TypeHelpers.GetAllStructuralMembers(typeInfo.Type);
            }

            // Now add on all of my "specific" properties
            foreach (md.EdmMember property in myProperties)
            {
                ColumnMap propertyColumnMap = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
                propertyColumnMapList.Add(propertyColumnMap);
            }

            // Create a map for myself
            ComplexTypeColumnMap columnMap = new ComplexTypeColumnMap(typeInfo.Type, name, propertyColumnMapList.ToArray(), nullSentinelColumnMap);

            // if a dictionary is supplied, add myself to the dictionary
            if (discriminatorMap != null)
            {
                discriminatorMap[typeInfo.TypeId] = columnMap;
            }
            if (allMaps != null)
            {
                allMaps.Add(columnMap);
            }
            // Finally walk through my subtypes - use the same column name
            foreach (TypeInfo subTypeInfo in typeInfo.ImmediateSubTypes)
            {
                CreateComplexTypeColumnMap(subTypeInfo, name, columnMap, discriminatorMap, allMaps);
            }

            return columnMap;
        }

        /// <summary>
        /// Create a column map for an entitytype column. 
        /// Currently, the key columns are not duplicated (ie) they point into the 
        /// same locations as in the properties list.
        /// Note: we also don't handle keys that are properties of nested fields
        /// </summary>
        /// <param name="typeInfo">Type information for the type</param>
        /// <param name="name">column name</param>
        /// <param name="superTypeColumnMap">supertype information if any</param>
        /// <param name="discriminatorMap">Dictionary of typeid->column map information</param>
        /// <param name="allMaps">List of all column maps (including those without typeid)</param>
        /// <param name="handleRelProperties">should we handle rel-properties?</param>
        /// <returns></returns>
        private EntityColumnMap CreateEntityColumnMap(TypeInfo typeInfo, string name, EntityColumnMap superTypeColumnMap,
            Dictionary<object, TypedColumnMap> discriminatorMap, List<TypedColumnMap> allMaps, bool handleRelProperties)
        {
            EntityColumnMap columnMap = null;
            List<ColumnMap> propertyColumnMapList = new List<ColumnMap>();

            // Copy over information from my supertype if it already exists
            if (superTypeColumnMap != null)
            {
                // get supertype properties
                foreach (ColumnMap c in superTypeColumnMap.Properties)
                {
                    propertyColumnMapList.Add(c);
                }
                // Now add on all of my "specific" properties
                foreach (md.EdmMember property in TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type))
                {
                    ColumnMap propertyColumnMap = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
                    propertyColumnMapList.Add(propertyColumnMap);
                }
                // create the entity column map w/ information from my supertype
                columnMap = new EntityColumnMap(typeInfo.Type, name, propertyColumnMapList.ToArray(), superTypeColumnMap.EntityIdentity);
            }
            else
            {
                SimpleColumnMap entitySetIdColumnMap = null;
                if (typeInfo.HasEntitySetIdProperty)
                {
                    entitySetIdColumnMap = CreateEntitySetIdColumnMap(typeInfo.EntitySetIdProperty);
                }

                // build up a list of key columns
                List<SimpleColumnMap> keyColumnMapList = new List<SimpleColumnMap>();
                // Create a dictionary to look up the key properties
                Dictionary<md.EdmProperty, ColumnMap> keyPropertyMap = new Dictionary<md.EdmProperty, ColumnMap>();

                foreach (md.EdmMember property in TypeHelpers.GetDeclaredStructuralMembers(typeInfo.Type))
                {
                    ColumnMap propertyColumnMap = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
                    propertyColumnMapList.Add(propertyColumnMap);
                    // add property to keymap, if this property is part of the key
                    if (md.TypeSemantics.IsPartOfKey(property))
                    {
                        md.EdmProperty edmProperty = property as md.EdmProperty;
                        PlanCompiler.Assert(edmProperty != null, "EntityType key member is not property?");
                        keyPropertyMap[edmProperty] = propertyColumnMap;
                    }
                }

                // Build up the key list if required
                foreach (md.EdmMember keyProperty in TypeHelpers.GetEdmType<md.EntityType>(typeInfo.Type).KeyMembers)
                {
                    md.EdmProperty edmKeyProperty = keyProperty as md.EdmProperty;
                    PlanCompiler.Assert(edmKeyProperty != null, "EntityType key member is not property?");
                    SimpleColumnMap keyColumnMap = keyPropertyMap[edmKeyProperty] as SimpleColumnMap;
                    PlanCompiler.Assert(keyColumnMap != null, "keyColumnMap is null");
                    keyColumnMapList.Add(keyColumnMap);
                }

                //
                // Create the entity identity. 
                //
                EntityIdentity identity = CreateEntityIdentity((md.EntityType)typeInfo.Type.EdmType, entitySetIdColumnMap, keyColumnMapList.ToArray());

                // finally create the entity column map
                columnMap = new EntityColumnMap(typeInfo.Type, name, propertyColumnMapList.ToArray(), identity);
            }

            // if a dictionary is supplied, add myself to the dictionary (abstract types need not be added)
            if (discriminatorMap != null)
            {
                // where DiscriminatedNewInstanceOp is used, there will not be an explicit type id for an abstract type
                // or types that do not appear in the QueryView
                // (the mapping will not include such information)
                if (null != typeInfo.TypeId)
                {
                    discriminatorMap[typeInfo.TypeId] = columnMap;
                }
            }
            if (allMaps != null)
            {
                allMaps.Add(columnMap);
            }
            // Finally walk through my subtypes
            foreach (TypeInfo subTypeInfo in typeInfo.ImmediateSubTypes)
            {
                CreateEntityColumnMap(subTypeInfo, name, columnMap, discriminatorMap, allMaps, false);
            }

            //
            // Build up the list of rel property column maps
            //
            if (handleRelProperties)
            {
                BuildRelPropertyColumnMaps(typeInfo, true);
            }
            return columnMap;
        }

        /// <summary>
        /// Build up the list of columnmaps for the relproperties. 
        /// Assumption: rel-properties follow after ALL the regular properties of the
        /// types in the type hierarchy.
        /// For now, we're simply going to ignore the rel-property columnmaps - we're
        /// just going to use this function to "drain" the corresponding vars
        /// </summary>
        /// <param name="typeInfo">typeinfo for the entity type</param>
        /// <param name="includeSupertypeRelProperties">should we get rel-properties from our supertype instances</param>
        private void BuildRelPropertyColumnMaps(TypeInfo typeInfo, bool includeSupertypeRelProperties)
        {
            //
            // Get the appropriate set of rel-properties
            //
            IEnumerable<RelProperty> relProperties = null;

            if (includeSupertypeRelProperties)
            {
                relProperties = m_typeInfo.RelPropertyHelper.GetRelProperties(typeInfo.Type.EdmType as md.EntityTypeBase);
            }
            else
            {
                relProperties = m_typeInfo.RelPropertyHelper.GetDeclaredOnlyRelProperties(typeInfo.Type.EdmType as md.EntityTypeBase);
            }

            //
            // Create a column-map for each rel-properties
            //
            foreach (RelProperty property in relProperties)
            {
                ColumnMap propertyColumnMap = CreateColumnMap(property.ToEnd.TypeUsage, property.ToString());
            }

            //
            // Add all subtypes
            //
            foreach (TypeInfo subTypeInfo in typeInfo.ImmediateSubTypes)
            {
                BuildRelPropertyColumnMaps(subTypeInfo, false);
            }
        }

        /// <summary>
        /// Create a column map for the entitysetid column
        /// </summary>
        /// <param name="prop"></param>
        /// <returns></returns>
        private SimpleColumnMap CreateEntitySetIdColumnMap(md.EdmProperty prop)
        {
            return CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(prop), c_EntitySetIdColumnName);
        }

        /// <summary>
        /// Creates a column map for a polymorphic type. This method first
        /// creates column maps for each type that is a subtype of the input type,
        /// and then creates a dictionary of typeid value -> column
        /// Finally, a PolymorphicColumnMap is created with these pieces of information
        /// </summary>
        /// <param name="typeInfo">Info about the type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private SimplePolymorphicColumnMap CreatePolymorphicColumnMap(TypeInfo typeInfo, string name)
        {
            // if the typeInfo has a DiscriminatorMap, use TrailingSpaceComparer to ensure that lookups
            // against discriminator values that SQL Server has right-padded (e.g. nchar and char) are properly
            // interpreted
            Dictionary<object, TypedColumnMap> discriminatorMap = new Dictionary<object, TypedColumnMap>(
                typeInfo.RootType.DiscriminatorMap == null ? null : TrailingSpaceComparer.Instance);
            // abstract types may not have discriminator values, but may nonetheless be interesting
            List<TypedColumnMap> allMaps = new List<TypedColumnMap>();

            // SQLBUDT #433011 -- Polymorphic types must construct column maps
            //                    that map to the entire type hierarchy, so we
            //                    need to use the RootType, not the current type.
            TypeInfo rootTypeInfo = typeInfo.RootType;

            // Get the type discriminant column first
            SimpleColumnMap typeIdColumnMap = CreateTypeIdColumnMap(rootTypeInfo.TypeIdProperty);

            // Prepare a place for the constructors to put the columns on the base
            // type, as they identify them.
            TypedColumnMap rootTypeColumnMap = null;

            // process complex/entity types appropriately
            // use the same name for the column 
            if (md.TypeSemantics.IsComplexType(typeInfo.Type))
            {
                rootTypeColumnMap = CreateComplexTypeColumnMap(rootTypeInfo, name, null, discriminatorMap, allMaps);
            }
            else
            {
                rootTypeColumnMap = CreateEntityColumnMap(rootTypeInfo, name, null, discriminatorMap, allMaps, true);
            }

            // Naturally, nothing is simple; we need to walk the rootTypeColumnMap hierarchy
            // and find the column map for the type that we are supposed to have as the base
            // type of this hierarchy.

            TypedColumnMap baseTypeColumnMap = null;
            foreach (TypedColumnMap value in allMaps)
            {
                if (md.TypeSemantics.IsStructurallyEqual(value.Type, typeInfo.Type))
                {
                    baseTypeColumnMap = value;
                    break;
                }
            }
            PlanCompiler.Assert(null != baseTypeColumnMap, "Didn't find requested type in polymorphic type hierarchy?");

            // Create a polymorphic column map
            SimplePolymorphicColumnMap result = new SimplePolymorphicColumnMap(typeInfo.Type, name, baseTypeColumnMap.Properties, typeIdColumnMap, discriminatorMap);
            return result;
        }

        /// <summary>
        /// Create a column map for a record type. Simply iterates through the
        /// list of fields, and produces a column map for each field
        /// </summary>
        /// <param name="typeInfo">Type information for the record type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private RecordColumnMap CreateRecordColumnMap(TypeInfo typeInfo, string name)
        {
            PlanCompiler.Assert(typeInfo.Type.EdmType is md.RowType, "not RowType");
            SimpleColumnMap nullSentinelColumnMap = null;
            if (typeInfo.HasNullSentinelProperty)
            {
                nullSentinelColumnMap = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(typeInfo.NullSentinelProperty), c_NullSentinelColumnName);
            }

            md.ReadOnlyMetadataCollection<md.EdmProperty> properties = TypeHelpers.GetProperties(typeInfo.Type);
            ColumnMap[] propertyColumnMapList = new ColumnMap[properties.Count];
            for (int i = 0; i < propertyColumnMapList.Length; ++i)
            {
                md.EdmMember property = properties[i];
                propertyColumnMapList[i] = CreateColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
            }

            RecordColumnMap result = new RecordColumnMap(typeInfo.Type, name, propertyColumnMapList, nullSentinelColumnMap);
            return result;
        }

        /// <summary>
        /// Create a column map for a ref type
        /// </summary>
        /// <param name="typeInfo">Type information for the ref type</param>
        /// <param name="name">Name of the column</param>
        /// <returns>Column map for the ref type</returns>
        private RefColumnMap CreateRefColumnMap(TypeInfo typeInfo, string name)
        {
            SimpleColumnMap entitySetIdColumnMap = null;
            if (typeInfo.HasEntitySetIdProperty)
            {
                entitySetIdColumnMap = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(typeInfo.EntitySetIdProperty), c_EntitySetIdColumnName);
            }

            // get the target entity type, 
            md.EntityType entityType = (md.EntityType)(TypeHelpers.GetEdmType<md.RefType>(typeInfo.Type).ElementType);

            // Iterate through the list of "key" properties
            SimpleColumnMap[] keyColList = new SimpleColumnMap[entityType.KeyMembers.Count];
            for (int i = 0; i < keyColList.Length; ++i)
            {
                md.EdmMember property = entityType.KeyMembers[i];
                keyColList[i] = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(property), property.Name);
            }

            // Create the entity identity
            EntityIdentity identity = CreateEntityIdentity(entityType, entitySetIdColumnMap, keyColList);

            RefColumnMap result = new RefColumnMap(typeInfo.Type, name, identity);
            return result;
        }

        /// <summary>
        /// Create a simple columnmap - applies only to scalar properties
        /// (Temporarily, also for collections)
        /// Simply picks up the next available column in the reader
        /// </summary>
        /// <param name="type">Column type</param>
        /// <param name="name">column name</param>
        /// <returns>Column map for this column</returns>
        private SimpleColumnMap CreateSimpleColumnMap(md.TypeUsage type, string name)
        {
            Var newVar = GetNextVar();
            SimpleColumnMap result = new VarRefColumnMap(type, name, newVar);
            return result;
        }

        /// <summary>
        /// Create a column map for the typeid column
        /// </summary>
        /// <param name="prop"></param>
        /// <returns></returns>
        private SimpleColumnMap CreateTypeIdColumnMap(md.EdmProperty prop)
        {
            return CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(prop), c_TypeIdColumnName);
        }

        /// <summary>
        /// Create a column map for a structural column - ref/complextype/entity/record
        /// </summary>
        /// <param name="type">Type info for the type</param>
        /// <param name="name">column name</param>
        /// <returns></returns>
        private ColumnMap CreateStructuralColumnMap(md.TypeUsage type, string name)
        {
            // Get our augmented type information for this type
            TypeInfo typeInfo = m_typeInfo.GetTypeInfo(type);

            // records?
            if (md.TypeSemantics.IsRowType(type))
            {
                return CreateRecordColumnMap(typeInfo, name);
            }

            // ref?
            if (md.TypeSemantics.IsReferenceType(type))
            {
                return CreateRefColumnMap(typeInfo, name);
            }

            // polymorphic type?
            if (typeInfo.HasTypeIdProperty)
            {
                return CreatePolymorphicColumnMap(typeInfo, name);
            }

            // process complex/entity types appropriately
            if (md.TypeSemantics.IsComplexType(type))
            {
                return CreateComplexTypeColumnMap(typeInfo, name, null, null, null);
            }

            if (md.TypeSemantics.IsEntityType(type))
            {
                return CreateEntityColumnMap(typeInfo, name, null, null, null, true);
            }

            // Anything else is not supported (this currently includes relationship types)
            throw EntityUtil.NotSupported(type.Identity);
        }

        /// <summary>
        /// Build out an EntityIdentity structure - for use by EntityColumnMap and RefColumnMap
        /// </summary>
        /// <param name="entityType">the entity type in question</param>
        /// <param name="entitySetIdColumnMap">column map for the entitysetid column</param>
        /// <param name="keyColumnMaps">column maps for the keys</param>
        /// <returns></returns>
        private EntityIdentity CreateEntityIdentity(md.EntityType entityType,
            SimpleColumnMap entitySetIdColumnMap,
            SimpleColumnMap[] keyColumnMaps)
        {
            //
            // If we have an entitysetid (and therefore, a column map for the entitysetid), 
            // then use a discriminated entity identity; otherwise, we use a simpleentityidentity
            // instead
            //
            if (entitySetIdColumnMap != null)
            {
                return new DiscriminatedEntityIdentity(entitySetIdColumnMap, m_typeInfo.EntitySetIdToEntitySetMap, keyColumnMaps);
            }
            else
            {
                md.EntitySet entitySet = m_typeInfo.GetEntitySet(entityType);
                PlanCompiler.Assert(entitySet != null, "Expected non-null entityset when no entitysetid is required. Entity type = " + entityType);
                return new SimpleEntityIdentity(entitySet, keyColumnMaps);
            }
        }
        #endregion
    }
}