File: StoreItemCollection.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (428 lines) | stat: -rw-r--r-- 19,284 bytes parent folder | download | duplicates (6)
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
//---------------------------------------------------------------------
// <copyright file="StoreItemCollection.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
namespace System.Data.Metadata.Edm
{
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Data.Common.Utils;
    using System.Data.Entity;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.Versioning;
    using System.Xml;

    /// <summary>
    /// Class for representing a collection of items in Store space.
    /// </summary>
    [CLSCompliant(false)]
    public sealed partial class StoreItemCollection : ItemCollection
    {
        #region Fields

        double _schemaVersion = XmlConstants.UndefinedVersion;

        // Cache for primitive type maps for Edm to provider
        private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes();
        private readonly Memoizer<EdmFunction, EdmFunction> _cachedCTypeFunction;

        private readonly DbProviderManifest _providerManifest;
        private readonly string _providerManifestToken;
        private readonly DbProviderFactory _providerFactory;
        
        // Storing the query cache manager in the store item collection since all queries are currently bound to the
        // store. So storing it in StoreItemCollection makes sense. Also, since query cache requires version and other
        // stuff of the provider, we can assume that the connection is always open and we have the store metadata.
        // Also we can use the same cache manager both for Entity Client and Object Query, since query cache has
        // no reference to any metadata in OSpace. Also we assume that ObjectMaterializer loads the assembly
        // before it tries to do object materialization, since we might not have loaded an assembly in another workspace
        // where this store item collection is getting reused
        private readonly System.Data.Common.QueryCache.QueryCacheManager _queryCacheManager = System.Data.Common.QueryCache.QueryCacheManager.Create();
        #endregion

        #region Constructors

        // used by EntityStoreSchemaGenerator to start with an empty (primitive types only) StoreItemCollection and 
        // add types discovered from the database
        internal StoreItemCollection(DbProviderFactory factory, DbProviderManifest manifest, string providerManifestToken)
            : base(DataSpace.SSpace)
        {
            Debug.Assert(factory != null, "factory is null");
            Debug.Assert(manifest != null, "manifest is null");

            _providerFactory = factory;
            _providerManifest = manifest;
            _providerManifestToken = providerManifestToken;
            _cachedCTypeFunction = new Memoizer<EdmFunction, EdmFunction>(ConvertFunctionSignatureToCType, null);
            LoadProviderManifest(_providerManifest, true /*checkForSystemNamespace*/);
        }

        /// <summary>
        /// constructor that loads the metadata files from the specified xmlReaders, and returns the list of errors
        /// encountered during load as the out parameter errors.
        /// 
        /// Publicly available from System.Data.Entity.Desgin.dll
        /// </summary>
        /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
        /// <param name="filePaths">the paths where the files can be found that match the xml readers collection</param>
        /// <param name="errors">An out parameter to return the collection of errors encountered while loading</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
        internal StoreItemCollection(IEnumerable<XmlReader> xmlReaders,
                                     System.Collections.ObjectModel.ReadOnlyCollection<string> filePaths,
                                     out IList<EdmSchemaError> errors)
            : base(DataSpace.SSpace)
        {
            // we will check the parameters for this internal ctor becuase
            // it is pretty much publicly exposed through the MetadataItemCollectionFactory
            // in System.Data.Entity.Design
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
            EntityUtil.CheckArgumentContainsNull(ref xmlReaders, "xmlReaders");
            EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");
            // filePaths is allowed to be null

            errors = this.Init(xmlReaders, filePaths, false,
                out _providerManifest,
                out _providerFactory,
                out _providerManifestToken,
                out _cachedCTypeFunction);
        }

        /// <summary>
        /// constructor that loads the metadata files from the specified xmlReaders, and returns the list of errors
        /// encountered during load as the out parameter errors.
        /// 
        /// Publicly available from System.Data.Entity.Desgin.dll
        /// </summary>
        /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
        /// <param name="filePaths">the paths where the files can be found that match the xml readers collection</param>
        internal StoreItemCollection(IEnumerable<XmlReader> xmlReaders,
                                     IEnumerable<string> filePaths)
            : base(DataSpace.SSpace)
        {
            EntityUtil.CheckArgumentNull(filePaths, "filePaths");
            EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");

            this.Init(xmlReaders, filePaths, true,
                out _providerManifest,
                out _providerFactory,
                out _providerManifestToken,
                out _cachedCTypeFunction);
        }

        /// <summary>
        /// Public constructor that loads the metadata files from the specified xmlReaders.
        /// Throws when encounter errors.
        /// </summary>
        /// <param name="xmlReaders">xmlReaders where the CDM schemas are loaded</param>
        public StoreItemCollection(IEnumerable<XmlReader> xmlReaders)
            : base(DataSpace.SSpace)
        {
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
            EntityUtil.CheckArgumentEmpty(ref xmlReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "xmlReader");

            MetadataArtifactLoader composite = MetadataArtifactLoader.CreateCompositeFromXmlReaders(xmlReaders);
            this.Init(composite.GetReaders(),
                      composite.GetPaths(), true,
                out _providerManifest,
                out _providerFactory,
                out _providerManifestToken,
                out _cachedCTypeFunction);

        }

        /// <summary>
        /// Constructs the new instance of StoreItemCollection
        /// with the list of CDM files provided.
        /// </summary>
        /// <param name="filePaths">paths where the CDM schemas are loaded</param>
        /// <exception cref="ArgumentException"> Thrown if path name is not valid</exception>
        /// <exception cref="System.ArgumentNullException">thrown if paths argument is null</exception>
        /// <exception cref="System.Data.MetadataException">For errors related to invalid schemas.</exception>
        [ResourceExposure(ResourceScope.Machine)] //Exposes the file path names which are a Machine resource
        [ResourceConsumption(ResourceScope.Machine)] //For MetadataArtifactLoader.CreateCompositeFromFilePaths method call but we do not create the file paths in this method 
        public StoreItemCollection(params string[] filePaths)
            : base(DataSpace.SSpace)
        {
            EntityUtil.CheckArgumentNull(filePaths, "filePaths");
            IEnumerable<string> enumerableFilePaths = filePaths;
            EntityUtil.CheckArgumentEmpty(ref enumerableFilePaths, Strings.StoreItemCollectionMustHaveOneArtifact, "filePaths");

            // Wrap the file paths in instances of the MetadataArtifactLoader class, which provides
            // an abstraction and a uniform interface over a diverse set of metadata artifacts.
            //
            MetadataArtifactLoader composite = null;
            List<XmlReader> readers = null;
            try
            {
                composite = MetadataArtifactLoader.CreateCompositeFromFilePaths(enumerableFilePaths, XmlConstants.SSpaceSchemaExtension);
                readers = composite.CreateReaders(DataSpace.SSpace);
                IEnumerable<XmlReader> ieReaders = readers.AsEnumerable();
                EntityUtil.CheckArgumentEmpty(ref ieReaders, Strings.StoreItemCollectionMustHaveOneArtifact, "filePaths");

                this.Init(readers, 
                          composite.GetPaths(DataSpace.SSpace), true,
                    out _providerManifest,
                    out _providerFactory,
                    out _providerManifestToken,
                    out _cachedCTypeFunction);
            }
            finally
            {
                if (readers != null)
                {
                    Helper.DisposeXmlReaders(readers);
                }
            }
        }


        

        private IList<EdmSchemaError> Init(IEnumerable<XmlReader> xmlReaders,
                                           IEnumerable<string> filePaths, bool throwOnError,
                                           out DbProviderManifest providerManifest,
                                           out DbProviderFactory providerFactory,
                                           out string providerManifestToken,
                                           out Memoizer<EdmFunction, EdmFunction> cachedCTypeFunction)
        {
            EntityUtil.CheckArgumentNull(xmlReaders, "xmlReaders");
            // 'filePaths' can be null

            cachedCTypeFunction = new Memoizer<EdmFunction, EdmFunction>(ConvertFunctionSignatureToCType, null);

            Loader loader = new Loader(xmlReaders, filePaths, throwOnError);
            providerFactory = loader.ProviderFactory;
            providerManifest = loader.ProviderManifest;
            providerManifestToken = loader.ProviderManifestToken;

            // load the items into the colleciton
            if (!loader.HasNonWarningErrors)
            {
                LoadProviderManifest(loader.ProviderManifest, true /* check for system namespace */);
                List<EdmSchemaError> errorList = EdmItemCollection.LoadItems(_providerManifest, loader.Schemas, this);
                foreach (var error in errorList)
                {
                    loader.Errors.Add(error);
                }
                
                if (throwOnError && errorList.Count != 0)
                    loader.ThrowOnNonWarningErrors();
            }
            
            return loader.Errors;
        }
                
        #endregion

        #region Properties
        /// <summary>
        /// Returns the query cache manager
        /// </summary>
        internal System.Data.Common.QueryCache.QueryCacheManager QueryCacheManager
        {
            get { return _queryCacheManager; }
        }

        internal DbProviderFactory StoreProviderFactory
        {
            get
            {
                return _providerFactory;
            }
        }

        internal DbProviderManifest StoreProviderManifest
        {
            get
            {
                return _providerManifest;
            }
        }

        internal string StoreProviderManifestToken
        {
            get
            {
                return _providerManifestToken;
            }
        }

        /// <summary>
        /// Version of this StoreItemCollection represents.
        /// </summary>
        public Double StoreSchemaVersion
        {
            get
            {
                return _schemaVersion;
            }
            internal set
            {
                _schemaVersion = value;
            }
        }

        #endregion

        #region Methods
        /// <summary>
        /// Get the list of primitive types for the given space
        /// </summary>
        /// <returns></returns>
        public System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> GetPrimitiveTypes()
        {
            return _primitiveTypeMaps.GetTypes();
        }

        /// <summary>
        /// Given the canonical primitive type, get the mapping primitive type in the given dataspace
        /// </summary>
        /// <param name="primitiveTypeKind">canonical primitive type</param>
        /// <returns>The mapped scalar type</returns>
        internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind primitiveTypeKind)
        {
            PrimitiveType type = null;
            _primitiveTypeMaps.TryGetType(primitiveTypeKind, null, out type);
            return type;
        }
               
        /// <summary>
        /// checks if the schemaKey refers to the provider manifest schema key 
        /// and if true, loads the provider manifest
        /// </summary>
        /// <param name="connection">The connection where the store manifest is loaded from</param>
        /// <param name="checkForSystemNamespace">Check for System namespace</param>
        /// <returns>The provider manifest object that was loaded</returns>
        private void LoadProviderManifest(DbProviderManifest storeManifest,
                                                      bool checkForSystemNamespace)
        {

            foreach (PrimitiveType primitiveType in storeManifest.GetStoreTypes())
            {
                //Add it to the collection and the primitive type maps
                this.AddInternal(primitiveType);
                _primitiveTypeMaps.Add(primitiveType);
            }

            foreach (EdmFunction function in storeManifest.GetStoreFunctions())
            {
                AddInternal(function);
            }
        }

        #endregion

        /// <summary>
        /// Get all the overloads of the function with the given name, this method is used for internal perspective
        /// </summary>
        /// <param name="functionName">The full name of the function</param>
        /// <param name="ignoreCase">true for case-insensitive lookup</param>
        /// <returns>A collection of all the functions with the given name in the given data space</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if functionaName argument passed in is null</exception>
        internal System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> GetCTypeFunctions(string functionName, bool ignoreCase)
        {
            System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> functionOverloads;

            if (this.FunctionLookUpTable.TryGetValue(functionName, out functionOverloads))
            {
                functionOverloads = ConvertToCTypeFunctions(functionOverloads);
                if (ignoreCase)
                {
                    return functionOverloads;
                }

                return GetCaseSensitiveFunctions(functionOverloads, functionName);
            }

            return Helper.EmptyEdmFunctionReadOnlyCollection;
        }

        private System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> ConvertToCTypeFunctions(
            System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> functionOverloads)
        {
            List<EdmFunction> cTypeFunctions = new List<EdmFunction>();
            foreach (var sTypeFunction in functionOverloads)
            {
                cTypeFunctions.Add(ConvertToCTypeFunction(sTypeFunction));
            }
            return cTypeFunctions.AsReadOnly();
        }

        internal EdmFunction ConvertToCTypeFunction(EdmFunction sTypeFunction)
        {
            return this._cachedCTypeFunction.Evaluate(sTypeFunction);
        }

        /// <summary>
        /// Convert the S type function parameters and returnType to C types.
        /// </summary>
        private EdmFunction ConvertFunctionSignatureToCType(EdmFunction sTypeFunction)
        {
            Debug.Assert(sTypeFunction.DataSpace == Edm.DataSpace.SSpace, "sTypeFunction.DataSpace == Edm.DataSpace.SSpace");

            if (sTypeFunction.IsFromProviderManifest)
            {
                return sTypeFunction;
            }
            
            FunctionParameter returnParameter = null;
            if (sTypeFunction.ReturnParameter != null)
            {
                TypeUsage edmTypeUsageReturnParameter =
                    MetadataHelper.ConvertStoreTypeUsageToEdmTypeUsage(sTypeFunction.ReturnParameter.TypeUsage);

                returnParameter =
                    new FunctionParameter(
                        sTypeFunction.ReturnParameter.Name,
                        edmTypeUsageReturnParameter,
                        sTypeFunction.ReturnParameter.GetParameterMode());
            }

            List<FunctionParameter> parameters = new List<FunctionParameter>();
            if (sTypeFunction.Parameters.Count > 0)
            {
                
                foreach (var parameter in sTypeFunction.Parameters)
                {
                    TypeUsage edmTypeUsage = MetadataHelper.ConvertStoreTypeUsageToEdmTypeUsage(parameter.TypeUsage);

                    FunctionParameter edmTypeParameter = new FunctionParameter(parameter.Name, edmTypeUsage, parameter.GetParameterMode());
                    parameters.Add(edmTypeParameter);
                }
            }

            FunctionParameter[] returnParameters = 
                returnParameter == null ? new FunctionParameter[0] : new FunctionParameter[] { returnParameter };
            EdmFunction edmFunction = new EdmFunction(sTypeFunction.Name, 
                sTypeFunction.NamespaceName,
                DataSpace.CSpace,
                new EdmFunctionPayload
                {
                    Schema = sTypeFunction.Schema,
                    StoreFunctionName = sTypeFunction.StoreFunctionNameAttribute,
                    CommandText = sTypeFunction.CommandTextAttribute,
                    IsAggregate = sTypeFunction.AggregateAttribute,
                    IsBuiltIn = sTypeFunction.BuiltInAttribute,
                    IsNiladic = sTypeFunction.NiladicFunctionAttribute,
                    IsComposable = sTypeFunction.IsComposableAttribute,
                    IsFromProviderManifest = sTypeFunction.IsFromProviderManifest,
                    IsCachedStoreFunction = true,
                    IsFunctionImport = sTypeFunction.IsFunctionImport,
                    ReturnParameters = returnParameters,
                    Parameters = parameters.ToArray(),
                    ParameterTypeSemantics = sTypeFunction.ParameterTypeSemanticsAttribute,
                });

            edmFunction.SetReadOnly();

            return edmFunction;
        }

    }//---- ItemCollection

}//----