1 //------------------------------------------------------------------------------
2 // <copyright file="recordstatefactory.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Collections.Generic;
9 using System.Data.Metadata.Edm;
11 using System.Linq.Expressions;
13 namespace System.Data.Common.Internal.Materialization
16 /// An immutable class used to generate new RecordStates, which are used
17 /// at runtime to produce value-layer (aka DataReader) results.
19 /// Contains static information collected by the Translator visitor. The
20 /// expressions produced by the Translator are compiled. The RecordStates
21 /// will refer to this object for all static information.
23 /// This class is cached in the query cache as part of the CoordinatorFactory.
25 internal class RecordStateFactory
30 /// Indicates which state slot in the Shaper.State is expected to hold the
31 /// value for this record state. Each unique record shape has it's own state
34 internal readonly int StateSlotNumber;
37 /// How many column values we have to reserve space for in this record.
39 internal readonly int ColumnCount;
42 /// The DataRecordInfo we must return for this record. If the record represents
43 /// an entity, this will be used to construct a unique EntityRecordInfo with the
44 /// EntityKey and EntitySet for the entity.
46 internal readonly DataRecordInfo DataRecordInfo;
49 /// A function that will gather the data for the row and store it on the record state.
51 internal readonly Func<Shaper, bool> GatherData;
54 /// Collection of nested records for this record, such as a complex type that is
55 /// part of an entity. This does not include records that are part of a nested
56 /// collection, however.
58 internal readonly System.Collections.ObjectModel.ReadOnlyCollection<RecordStateFactory> NestedRecordStateFactories;
61 /// The name for each column.
63 internal readonly System.Collections.ObjectModel.ReadOnlyCollection<string> ColumnNames;
66 /// The type usage information for each column.
68 internal readonly System.Collections.ObjectModel.ReadOnlyCollection<TypeUsage> TypeUsages;
71 /// Tracks which columns might need special handling (nested readers/records)
73 internal readonly System.Collections.ObjectModel.ReadOnlyCollection<bool> IsColumnNested;
76 /// Tracks whether there are ANY columns that need special handling.
78 internal readonly bool HasNestedColumns;
81 /// A helper class to make the translation from name->ordinal.
83 internal readonly FieldNameLookup FieldNameLookup;
86 /// Description of this RecordStateFactory, used for debugging only; while this
87 /// is not needed in retail code, it is pretty important because it's the only
88 /// description we'll have once we compile the Expressions; debugging a problem
89 /// with retail bits would be pretty hard without this.
91 private readonly string Description;
97 public RecordStateFactory(int stateSlotNumber, int columnCount, RecordStateFactory[] nestedRecordStateFactories, DataRecordInfo dataRecordInfo, Expression gatherData, string[] propertyNames, TypeUsage[] typeUsages)
99 this.StateSlotNumber = stateSlotNumber;
100 this.ColumnCount = columnCount;
101 this.NestedRecordStateFactories = new System.Collections.ObjectModel.ReadOnlyCollection<RecordStateFactory>(nestedRecordStateFactories);
102 this.DataRecordInfo = dataRecordInfo;
103 this.GatherData = Translator.Compile<bool>(gatherData);
104 this.Description = gatherData.ToString();
105 this.ColumnNames = new System.Collections.ObjectModel.ReadOnlyCollection<string>(propertyNames);
106 this.TypeUsages = new System.Collections.ObjectModel.ReadOnlyCollection<TypeUsage>(typeUsages);
108 this.FieldNameLookup = new FieldNameLookup(this.ColumnNames, -1);
110 // pre-compute the nested objects from typeUsage, for performance
111 bool[] isColumnNested = new bool[columnCount];
113 for (int ordinal = 0; ordinal < columnCount; ordinal++)
115 switch (typeUsages[ordinal].EdmType.BuiltInTypeKind)
117 case BuiltInTypeKind.EntityType:
118 case BuiltInTypeKind.ComplexType:
119 case BuiltInTypeKind.RowType:
120 case BuiltInTypeKind.CollectionType:
121 isColumnNested[ordinal] = true;
122 this.HasNestedColumns = true;
125 isColumnNested[ordinal] = false;
129 this.IsColumnNested = new System.Collections.ObjectModel.ReadOnlyCollection<bool>(isColumnNested);
134 #region "public" surface area
137 /// It's GO time, create the record state.
139 internal RecordState Create(CoordinatorFactory coordinatorFactory)
141 return new RecordState(this, coordinatorFactory);