Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Common / Internal / Materialization / RecordStateFactory.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="recordstatefactory.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 using System.Collections.Generic;
9 using System.Data.Metadata.Edm;
10 using System.Linq;
11 using System.Linq.Expressions;
12
13 namespace System.Data.Common.Internal.Materialization
14 {
15     /// <summary>
16     /// An immutable class used to generate new RecordStates, which are used
17     /// at runtime to produce value-layer (aka DataReader) results.  
18     /// 
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.
22     /// 
23     /// This class is cached in the query cache as part of the CoordinatorFactory.
24     /// </summary>
25     internal class RecordStateFactory
26     {
27         #region state
28
29         /// <summary>
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
32         /// slot.
33         /// </summary>
34         internal readonly int StateSlotNumber;
35
36         /// <summary>
37         /// How many column values we have to reserve space for in this record.
38         /// </summary>
39         internal readonly int ColumnCount;
40
41         /// <summary>
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.
45         /// </summary>
46         internal readonly DataRecordInfo DataRecordInfo;
47
48         /// <summary>
49         /// A function that will gather the data for the row and store it on the record state.
50         /// </summary>
51         internal readonly Func<Shaper, bool> GatherData;
52
53         /// <summary>
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.
57         /// </summary>
58         internal readonly System.Collections.ObjectModel.ReadOnlyCollection<RecordStateFactory> NestedRecordStateFactories;
59
60         /// <summary>
61         /// The name for each column.
62         /// </summary>
63         internal readonly System.Collections.ObjectModel.ReadOnlyCollection<string> ColumnNames;
64
65         /// <summary>
66         /// The type usage information for each column.
67         /// </summary>
68         internal readonly System.Collections.ObjectModel.ReadOnlyCollection<TypeUsage> TypeUsages;
69
70         /// <summary>
71         /// Tracks which columns might need special handling (nested readers/records)
72         /// </summary>
73         internal readonly System.Collections.ObjectModel.ReadOnlyCollection<bool> IsColumnNested;
74
75         /// <summary>
76         /// Tracks whether there are ANY columns that need special handling.
77         /// </summary>
78         internal readonly bool HasNestedColumns;
79
80         /// <summary>
81         /// A helper class to make the translation from name->ordinal.
82         /// </summary>
83         internal readonly FieldNameLookup FieldNameLookup;
84
85         /// <summary>
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.
90         /// </summary>
91         private readonly string Description;
92
93         #endregion
94
95         #region constructor
96
97         public RecordStateFactory(int stateSlotNumber, int columnCount, RecordStateFactory[] nestedRecordStateFactories, DataRecordInfo dataRecordInfo, Expression gatherData, string[] propertyNames, TypeUsage[] typeUsages)
98         {
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);
107
108             this.FieldNameLookup = new FieldNameLookup(this.ColumnNames, -1);
109
110             // pre-compute the nested objects from typeUsage, for performance
111             bool[] isColumnNested = new bool[columnCount];
112
113             for (int ordinal = 0; ordinal < columnCount; ordinal++)
114             {
115                 switch (typeUsages[ordinal].EdmType.BuiltInTypeKind)
116                 {
117                     case BuiltInTypeKind.EntityType:
118                     case BuiltInTypeKind.ComplexType:
119                     case BuiltInTypeKind.RowType:
120                     case BuiltInTypeKind.CollectionType:
121                         isColumnNested[ordinal] = true;
122                         this.HasNestedColumns = true;
123                         break;
124                     default:
125                         isColumnNested[ordinal] = false;
126                         break;
127                 }
128             }
129             this.IsColumnNested = new System.Collections.ObjectModel.ReadOnlyCollection<bool>(isColumnNested);
130         }
131
132         #endregion
133
134         #region "public" surface area
135
136         /// <summary>
137         /// It's GO time, create the record state.
138         /// </summary>
139         internal RecordState Create(CoordinatorFactory coordinatorFactory)
140         {
141             return new RecordState(this, coordinatorFactory);
142         }
143
144         #endregion
145     }
146
147 }