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
}//----
|