Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Metadata / ObjectItemCollection.cs / 2 / ObjectItemCollection.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Data.Common.Utils;
using System.Diagnostics;
using System.Collections.ObjectModel;
// Using an alias for this because a lot of names in this namespace conflicts with names in metadata
using DataClasses = System.Data.Objects.DataClasses;
using System.Globalization;
using System.Data.Entity;
using System.Data.Common;
namespace System.Data.Metadata.Edm
{
///
/// Class for representing a collection of items for the object layer.
/// Most of the implemetation for actual maintainance of the collection is
/// done by ItemCollection
///
public sealed partial class ObjectItemCollection : ItemCollection
{
#region Constructors
///
/// The ObjectItemCollection that loads metadata from assemblies
///
public ObjectItemCollection()
: base(DataSpace.OSpace)
{
foreach (PrimitiveType type in ClrProviderManifest.Instance.GetStoreTypes())
{
AddInternal(type);
_primitiveTypeMaps.Add(type);
}
}
#endregion
#region Fields
// Cache for primitive type maps for Edm to provider
private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes();
// Used for tracking the loading of an assembly and its referenced assemblies. Though the value of an entry is bool, the logic represented
// by an entry is tri-state, the third state represented by a "missing" entry. To summarize:
// 1. The associated with an is "true" : Specified and all referenced assemblies have been loaded
// 2. The associated with an is "false" : Specified assembly loaded. Its referenced assemblies may not be loaded
// 3. The is missing : Specified assembly has not been loaded
private Dictionary _knownAssemblies = new Dictionary();
// Dictionary which keeps tracks of oc mapping information - the key is the conceptual name of the type
// and the value is the reference to the ospace type
private Dictionary _ocMapping = new Dictionary();
private const string EcmPublicKeyToken = "PublicKeyToken=" + AssemblyRef.EcmaPublicKey;
private object _loadAssemblyLock = new object();
internal object LoadAssemblyLock
{
get
{
return _loadAssemblyLock;
}
}
internal static IList ViewGenerationAssemblies
{
get
{
return AssemblyCacheEntry.ViewGenerationAssemblies;
}
}
#endregion
#region Methods
/// Is the assembly and its referened assemblies not expected to have any metadata
internal static bool ShouldFilterAssembly(string fullName)
{
return (fullName.EndsWith(EcmPublicKeyToken, StringComparison.OrdinalIgnoreCase));
}
internal static bool IsSchemaAttributePresent(Assembly assembly)
{
return assembly.IsDefined(typeof(DataClasses.EdmSchemaAttribute), false /*inherit*/);
}
internal static bool IsCompiledViewGenAttributePresent(Assembly assembly)
{
return assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
}
///
/// The method loads the O-space metadata for all the referenced assemblies starting from the given assembly
/// in a recursive way.
/// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
///
/// assembly whose dependency list we are going to traverse
internal void LoadAllReferencedAssemblies(Assembly assembly)
{
this.LoadAllReferencedAssemblies(assembly, false);
}
///
/// The method loads all the referenced assemblies starting from the given assembly in a recursive way.
/// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
///
/// assembly whose dependency list we are going to traverse
///
internal void LoadAllReferencedAssemblies(Assembly assembly, bool loadOnlyViewGenInfo)
{
if (loadOnlyViewGenInfo)
{
if (!ShouldFilterAssembly(assembly.FullName))
{
lock (this)
{
CollectIfViewGenAssembly(assembly);
foreach (AssemblyName asmName in assembly.GetReferencedAssemblies())
{
string fullName = asmName.FullName;
if (!ShouldFilterAssembly(fullName))
{
// filter out "known" assemblies to prevent unnecessary loading
Bid.Trace(" loadededAssembly='%ls'\n", fullName);
Assembly loadedAssembly = AssemblyCacheEntry.SafeLoadReferencedAssembly(fullName);
if (loadedAssembly == null)
{
continue;
}
CollectIfViewGenAssembly(loadedAssembly);
}
}
}
}
}
else
{
LoadAssemblyFromCache(this, assembly, true /*loadAllReferencedAssemblies*/);
}
}
///
/// Load metadata from the given assembly
///
/// The assembly from which to load metadata
/// thrown if assembly argument is null
public void LoadFromAssembly(Assembly assembly)
{
EntityUtil.CheckArgumentNull(assembly, "assembly");
EntityBid.Trace(" assembly='%ls'\n", assembly.FullName);
LoadAssemblyFromCache(this, assembly, false /*loadAllReferencedAssemblies*/);
//Since User called LoadFromAssembly, so we should collect the generated views if present
//even if the schema attribute is not present
if (IsCompiledViewGenAttributePresent(assembly) && !IsSchemaAttributePresent(assembly) )
{
CollectIfViewGenAssembly(assembly);
}
}
///
/// Load metadata from the type's assembly.
///
/// The type's assembly is loaded into the OSpace ItemCollection
/// true if the type and all its generic arguments are filtered out (did not attempt to load assembly)
internal bool LoadAssemblyForType(Type type)
{
bool result;
// InternalLoadFromAssembly will check _knownAssemblies
result = LoadAssemblyFromCache(this, type.Assembly, false /*loadAllReferencedAssemblies*/);
if (type.IsGenericType)
{
// recursively load all generic types
// interesting code paths are ObjectQuery>, ObjectQuery>
foreach (Type t in type.GetGenericArguments())
{
result |= LoadAssemblyForType(t);
}
}
return result;
}
///
/// internal static method to get the relationship name
///
///
///
///
internal AssociationType GetRelationshipType(Type entityClrType, string relationshipName, out string fullSearchName)
{
fullSearchName = relationshipName;
AssociationType associationType;
if (TryGetItem(relationshipName, out associationType))
{
return associationType;
}
else if (!IsQualifiedName(relationshipName))
{
// they send us unqualified relationship names, try to make it fully qualified
EntityType entityType;
if (TryGetItem(entityClrType.FullName, out entityType))
{
// get the c-space namespace
string namespaceName = System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)entityType).CSpaceTypeName);
fullSearchName = namespaceName + "." + relationshipName;
if(TryGetItem(fullSearchName, out associationType))
{
return associationType;
}
}
}
return null;
}
///
/// Loads the OSpace types in the assembly and returns them as a dictionary
///
/// The assembly to load
/// A mapping from names to OSpace EdmTypes
private static Dictionary LoadTypesExpensiveWay(Assembly assembly)
{
Dictionary typesInLoading = null;
// If the assembly is not one of the filtered assemblies and has the schema attribute
if (!ShouldFilterAssembly(assembly.FullName) && IsSchemaAttributePresent(assembly))
{
List errors;
Dictionary knownAssemblies = new Dictionary();
AssemblyCacheEntry.LoadAssemblyFromCache(assembly, false /*loadAllReferencedAssemblies*/,
knownAssemblies, out typesInLoading, out errors);
// Check for errors
if (errors.Count != 0)
{
throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
}
}
return typesInLoading;
}
///
/// internal static method to get the relationship name
///
///
///
///
internal static AssociationType GetRelationshipTypeExpensiveWay(Type entityClrType, string relationshipName, out string fullSearchName)
{
fullSearchName = relationshipName;
Dictionary typesInLoading = LoadTypesExpensiveWay(entityClrType.Assembly);
if (typesInLoading != null)
{
EdmType edmType;
// Look in typesInLoading for relationship type
if (typesInLoading.TryGetValue(relationshipName, out edmType) &&
Helper.IsRelationshipType(edmType))
{
return (AssociationType)edmType;
}
else if (!IsQualifiedName(relationshipName))
{
string namespaceName = GetModelNamespaceForEntityType(typesInLoading, entityClrType);
fullSearchName = namespaceName + "." + relationshipName;
if (namespaceName != null &&
typesInLoading.TryGetValue(fullSearchName, out edmType) &&
Helper.IsRelationshipType(edmType))
{
return (AssociationType)edmType;
}
}
}
return null;
}
///
/// internal static method to get all the AssociationTypes from an assembly
///
/// The assembly from which to load relationship types
/// An enumeration of OSpace AssociationTypes that are present in this assembly
internal static IEnumerable GetAllRelationshipTypesExpensiveWay(Assembly assembly)
{
Dictionary typesInLoading = LoadTypesExpensiveWay(assembly);
if (typesInLoading != null)
{
// Iterate through the EdmTypes looking for AssociationTypes
foreach (EdmType edmType in typesInLoading.Values)
{
if (Helper.IsAssociationType(edmType))
{
yield return (AssociationType)edmType;
}
}
}
yield break;
}
private static string GetModelNamespaceForEntityType(Dictionary typesInLoading,Type entityClrType)
{
EdmType edmType;
if(typesInLoading.TryGetValue(entityClrType.FullName, out edmType) &&
Helper.IsEntityType(edmType))
{
return System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)edmType).CSpaceTypeName);
}
return null;
}
private static bool IsQualifiedName(string relationshipName)
{
return relationshipName.Contains(".");
}
private static bool LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly,
bool loadReferencedAssemblies)
{
if (ShouldFilterAssembly(assembly.FullName))
{
return false;
}
// Check if its loaded in the cache - if the call is for loading referenced assemblies, make sure that all referenced
// assemblies are also loaded
bool areReferencedAssembliesLoaded;
if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
{
// Proceed if only we need to load the referenced assemblies and they are not loaded
if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
{
return true;
}
}
// Check for schema attribute - if we need to load all the referenced assemblies, then we should continue
// even if the root assembly doesn't have the attribute present
if (!IsSchemaAttributePresent(assembly) && !loadReferencedAssemblies)
{
return false;
}
lock (objectItemCollection.LoadAssemblyLock)
{
// Check after acquiring the lock, since the known assemblies might have got modified
// Check if the assembly is already loaded. The reason we need to check if the assembly is already loaded, is that
if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
{
// Proceed if only we need to load the referenced assemblies and they are not loaded
if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
{
return true;
}
}
Dictionary typesInLoading;
List errors;
Dictionary knownAssemblies;
if (objectItemCollection != null)
{
knownAssemblies = new Dictionary(objectItemCollection._knownAssemblies);
}
else
{
knownAssemblies = new Dictionary();
}
// Load the assembly from the cache
AssemblyCacheEntry.LoadAssemblyFromCache(assembly, loadReferencedAssemblies, knownAssemblies, out typesInLoading, out errors);
// Throw if we have encountered errors
if (errors.Count != 0)
{
throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
}
// We can encounter new assemblies, but they may not have any time in them
if (typesInLoading.Count != 0)
{
Debug.Assert(knownAssemblies.Count != objectItemCollection._knownAssemblies.Count,
"Since there are no types loaded, some assemblies must have got loaded");
// No errors, so go ahead and add the types and make them readonly
// The existence of the loading lock tells us whether we should be thread safe or not, if we need
// to be thread safe, then we need to use AtomicAddRange. We don't need to actually use the lock
// because the caller should have done it already
// Recheck the assemblies added, another list is created just to match up the collection type
// taken in by AtomicAddRange()
List globalItems = new List();
foreach (EdmType edmType in typesInLoading.Values)
{
globalItems.Add(edmType);
try
{
// Also populate the ocmapping information
if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind)
{
objectItemCollection._ocMapping.Add(((ClrEntityType)edmType).CSpaceTypeName, edmType);
}
else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
{
objectItemCollection._ocMapping.Add(((ClrComplexType)edmType).CSpaceTypeName, edmType);
}
// for rest of the types like relationship type, we do not have oc mapping, so we don't keep
// to keep that information
}
catch (ArgumentException e)
{
throw new MappingException(Strings.Mapping_CannotMapCLRTypeMultipleTimes(edmType.Identity), e);
}
}
// Create a new ObjectItemCollection and add all the global items to it.
// Also copy all the existing items from the existing collection
objectItemCollection.AtomicAddRange(globalItems);
// Update the value of known assemblies
objectItemCollection._knownAssemblies = knownAssemblies;
foreach (Assembly loadedAssembly in knownAssemblies.Keys)
{
CollectIfViewGenAssembly(loadedAssembly);
}
}
}
return true;
}
///
/// Check to see if the assembly has the custom view generation attribute AND
/// collect the assembly into the local list if it has cutom attribute.
///
///
///
private static void CollectIfViewGenAssembly(Assembly assembly)
{
if (assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/))
{
if (!AssemblyCacheEntry.ViewGenerationAssemblies.Contains(assembly))
{
AssemblyCacheEntry.ViewGenerationAssemblies.Add(assembly);
}
}
}
///
/// Get the list of primitive types for the given space
///
///
public IEnumerable GetPrimitiveTypes()
{
return _primitiveTypeMaps.GetTypes();
}
///
/// The method returns the underlying CLR type for the specified OSpace type argument.
/// If the DataSpace of the parameter is not OSpace, an ArgumentException is thrown.
///
/// The OSpace type to look up
/// The CLR type of the OSpace argument
public Type GetClrType(StructuralType objectSpaceType)
{
Type clrType;
if (!this.TryGetClrType(objectSpaceType, out clrType))
{
throw EntityUtil.Argument(Strings.FailedToFindClrTypeMapping(objectSpaceType.Identity));
}
return clrType;
}
///
/// The method returns the underlying CLR type for the specified OSpace type argument.
/// If the DataSpace of the parameter is not OSpace, the method returns false and sets
/// the out parameter to null.
///
/// The OSpace type to look up
/// The CLR type of the OSpace argument
/// true on success, false on failure
public bool TryGetClrType(StructuralType objectSpaceType, out Type clrType)
{
EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType");
if (objectSpaceType.DataSpace != DataSpace.OSpace)
{
throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType");
}
clrType = null;
if (BuiltInTypeKind.EntityType == objectSpaceType.BuiltInTypeKind)
{
clrType = ((ClrEntityType)objectSpaceType).ClrType;
}
else
if (BuiltInTypeKind.ComplexType == objectSpaceType.BuiltInTypeKind)
{
clrType = ((ClrComplexType)objectSpaceType).ClrType;
}
return clrType != null;
}
///
/// Given the canonical primitive type, get the mapping primitive type in the given dataspace
///
/// canonical primitive type
/// The mapped scalar type
internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind modelType)
{
PrimitiveType type = null;
_primitiveTypeMaps.TryGetType(modelType, null, out type);
return type;
}
///
/// Get the OSpace type given the CSpace typename
///
///
///
///
///
internal bool TryGetOSpaceType(EdmType cspaceType, out EdmType edmType)
{
Debug.Assert(DataSpace.CSpace == cspaceType.DataSpace, "DataSpace should be CSpace");
// check if there is an entity or complex type mapping with this name
if (BuiltInTypeKind.EntityType == cspaceType.BuiltInTypeKind ||
BuiltInTypeKind.ComplexType == cspaceType.BuiltInTypeKind)
{
return _ocMapping.TryGetValue(cspaceType.Identity, out edmType);
}
return TryGetItem(cspaceType.Identity, out edmType);
}
///
/// Given the ospace type, returns the fullname of the mapped cspace type.
/// Today, since we allow non-default mapping between entity type and complex type,
/// this is only possible for entity and complex type.
///
///
///
internal static string TryGetMappingCSpaceTypeIdentity(EdmType edmType)
{
Debug.Assert(DataSpace.OSpace == edmType.DataSpace, "DataSpace must be OSpace");
if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind)
{
return ((ClrEntityType)edmType).CSpaceTypeName;
}
else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
{
return ((ClrComplexType)edmType).CSpaceTypeName;
}
return edmType.Identity;
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Data.Common.Utils;
using System.Diagnostics;
using System.Collections.ObjectModel;
// Using an alias for this because a lot of names in this namespace conflicts with names in metadata
using DataClasses = System.Data.Objects.DataClasses;
using System.Globalization;
using System.Data.Entity;
using System.Data.Common;
namespace System.Data.Metadata.Edm
{
///
/// Class for representing a collection of items for the object layer.
/// Most of the implemetation for actual maintainance of the collection is
/// done by ItemCollection
///
public sealed partial class ObjectItemCollection : ItemCollection
{
#region Constructors
///
/// The ObjectItemCollection that loads metadata from assemblies
///
public ObjectItemCollection()
: base(DataSpace.OSpace)
{
foreach (PrimitiveType type in ClrProviderManifest.Instance.GetStoreTypes())
{
AddInternal(type);
_primitiveTypeMaps.Add(type);
}
}
#endregion
#region Fields
// Cache for primitive type maps for Edm to provider
private readonly CacheForPrimitiveTypes _primitiveTypeMaps = new CacheForPrimitiveTypes();
// Used for tracking the loading of an assembly and its referenced assemblies. Though the value of an entry is bool, the logic represented
// by an entry is tri-state, the third state represented by a "missing" entry. To summarize:
// 1. The associated with an is "true" : Specified and all referenced assemblies have been loaded
// 2. The associated with an is "false" : Specified assembly loaded. Its referenced assemblies may not be loaded
// 3. The is missing : Specified assembly has not been loaded
private Dictionary _knownAssemblies = new Dictionary();
// Dictionary which keeps tracks of oc mapping information - the key is the conceptual name of the type
// and the value is the reference to the ospace type
private Dictionary _ocMapping = new Dictionary();
private const string EcmPublicKeyToken = "PublicKeyToken=" + AssemblyRef.EcmaPublicKey;
private object _loadAssemblyLock = new object();
internal object LoadAssemblyLock
{
get
{
return _loadAssemblyLock;
}
}
internal static IList ViewGenerationAssemblies
{
get
{
return AssemblyCacheEntry.ViewGenerationAssemblies;
}
}
#endregion
#region Methods
/// Is the assembly and its referened assemblies not expected to have any metadata
internal static bool ShouldFilterAssembly(string fullName)
{
return (fullName.EndsWith(EcmPublicKeyToken, StringComparison.OrdinalIgnoreCase));
}
internal static bool IsSchemaAttributePresent(Assembly assembly)
{
return assembly.IsDefined(typeof(DataClasses.EdmSchemaAttribute), false /*inherit*/);
}
internal static bool IsCompiledViewGenAttributePresent(Assembly assembly)
{
return assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/);
}
///
/// The method loads the O-space metadata for all the referenced assemblies starting from the given assembly
/// in a recursive way.
/// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
///
/// assembly whose dependency list we are going to traverse
internal void LoadAllReferencedAssemblies(Assembly assembly)
{
this.LoadAllReferencedAssemblies(assembly, false);
}
///
/// The method loads all the referenced assemblies starting from the given assembly in a recursive way.
/// The assembly should be from Assembly.GetCallingAssembly via one of our public API's.
///
/// assembly whose dependency list we are going to traverse
///
internal void LoadAllReferencedAssemblies(Assembly assembly, bool loadOnlyViewGenInfo)
{
if (loadOnlyViewGenInfo)
{
if (!ShouldFilterAssembly(assembly.FullName))
{
lock (this)
{
CollectIfViewGenAssembly(assembly);
foreach (AssemblyName asmName in assembly.GetReferencedAssemblies())
{
string fullName = asmName.FullName;
if (!ShouldFilterAssembly(fullName))
{
// filter out "known" assemblies to prevent unnecessary loading
Bid.Trace(" loadededAssembly='%ls'\n", fullName);
Assembly loadedAssembly = AssemblyCacheEntry.SafeLoadReferencedAssembly(fullName);
if (loadedAssembly == null)
{
continue;
}
CollectIfViewGenAssembly(loadedAssembly);
}
}
}
}
}
else
{
LoadAssemblyFromCache(this, assembly, true /*loadAllReferencedAssemblies*/);
}
}
///
/// Load metadata from the given assembly
///
/// The assembly from which to load metadata
/// thrown if assembly argument is null
public void LoadFromAssembly(Assembly assembly)
{
EntityUtil.CheckArgumentNull(assembly, "assembly");
EntityBid.Trace(" assembly='%ls'\n", assembly.FullName);
LoadAssemblyFromCache(this, assembly, false /*loadAllReferencedAssemblies*/);
//Since User called LoadFromAssembly, so we should collect the generated views if present
//even if the schema attribute is not present
if (IsCompiledViewGenAttributePresent(assembly) && !IsSchemaAttributePresent(assembly) )
{
CollectIfViewGenAssembly(assembly);
}
}
///
/// Load metadata from the type's assembly.
///
/// The type's assembly is loaded into the OSpace ItemCollection
/// true if the type and all its generic arguments are filtered out (did not attempt to load assembly)
internal bool LoadAssemblyForType(Type type)
{
bool result;
// InternalLoadFromAssembly will check _knownAssemblies
result = LoadAssemblyFromCache(this, type.Assembly, false /*loadAllReferencedAssemblies*/);
if (type.IsGenericType)
{
// recursively load all generic types
// interesting code paths are ObjectQuery>, ObjectQuery>
foreach (Type t in type.GetGenericArguments())
{
result |= LoadAssemblyForType(t);
}
}
return result;
}
///
/// internal static method to get the relationship name
///
///
///
///
internal AssociationType GetRelationshipType(Type entityClrType, string relationshipName, out string fullSearchName)
{
fullSearchName = relationshipName;
AssociationType associationType;
if (TryGetItem(relationshipName, out associationType))
{
return associationType;
}
else if (!IsQualifiedName(relationshipName))
{
// they send us unqualified relationship names, try to make it fully qualified
EntityType entityType;
if (TryGetItem(entityClrType.FullName, out entityType))
{
// get the c-space namespace
string namespaceName = System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)entityType).CSpaceTypeName);
fullSearchName = namespaceName + "." + relationshipName;
if(TryGetItem(fullSearchName, out associationType))
{
return associationType;
}
}
}
return null;
}
///
/// Loads the OSpace types in the assembly and returns them as a dictionary
///
/// The assembly to load
/// A mapping from names to OSpace EdmTypes
private static Dictionary LoadTypesExpensiveWay(Assembly assembly)
{
Dictionary typesInLoading = null;
// If the assembly is not one of the filtered assemblies and has the schema attribute
if (!ShouldFilterAssembly(assembly.FullName) && IsSchemaAttributePresent(assembly))
{
List errors;
Dictionary knownAssemblies = new Dictionary();
AssemblyCacheEntry.LoadAssemblyFromCache(assembly, false /*loadAllReferencedAssemblies*/,
knownAssemblies, out typesInLoading, out errors);
// Check for errors
if (errors.Count != 0)
{
throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
}
}
return typesInLoading;
}
///
/// internal static method to get the relationship name
///
///
///
///
internal static AssociationType GetRelationshipTypeExpensiveWay(Type entityClrType, string relationshipName, out string fullSearchName)
{
fullSearchName = relationshipName;
Dictionary typesInLoading = LoadTypesExpensiveWay(entityClrType.Assembly);
if (typesInLoading != null)
{
EdmType edmType;
// Look in typesInLoading for relationship type
if (typesInLoading.TryGetValue(relationshipName, out edmType) &&
Helper.IsRelationshipType(edmType))
{
return (AssociationType)edmType;
}
else if (!IsQualifiedName(relationshipName))
{
string namespaceName = GetModelNamespaceForEntityType(typesInLoading, entityClrType);
fullSearchName = namespaceName + "." + relationshipName;
if (namespaceName != null &&
typesInLoading.TryGetValue(fullSearchName, out edmType) &&
Helper.IsRelationshipType(edmType))
{
return (AssociationType)edmType;
}
}
}
return null;
}
///
/// internal static method to get all the AssociationTypes from an assembly
///
/// The assembly from which to load relationship types
/// An enumeration of OSpace AssociationTypes that are present in this assembly
internal static IEnumerable GetAllRelationshipTypesExpensiveWay(Assembly assembly)
{
Dictionary typesInLoading = LoadTypesExpensiveWay(assembly);
if (typesInLoading != null)
{
// Iterate through the EdmTypes looking for AssociationTypes
foreach (EdmType edmType in typesInLoading.Values)
{
if (Helper.IsAssociationType(edmType))
{
yield return (AssociationType)edmType;
}
}
}
yield break;
}
private static string GetModelNamespaceForEntityType(Dictionary typesInLoading,Type entityClrType)
{
EdmType edmType;
if(typesInLoading.TryGetValue(entityClrType.FullName, out edmType) &&
Helper.IsEntityType(edmType))
{
return System.Data.EntityModel.SchemaObjectModel.Utils.GetEverythingBeforeLastPeriod(((ClrEntityType)edmType).CSpaceTypeName);
}
return null;
}
private static bool IsQualifiedName(string relationshipName)
{
return relationshipName.Contains(".");
}
private static bool LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly,
bool loadReferencedAssemblies)
{
if (ShouldFilterAssembly(assembly.FullName))
{
return false;
}
// Check if its loaded in the cache - if the call is for loading referenced assemblies, make sure that all referenced
// assemblies are also loaded
bool areReferencedAssembliesLoaded;
if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
{
// Proceed if only we need to load the referenced assemblies and they are not loaded
if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
{
return true;
}
}
// Check for schema attribute - if we need to load all the referenced assemblies, then we should continue
// even if the root assembly doesn't have the attribute present
if (!IsSchemaAttributePresent(assembly) && !loadReferencedAssemblies)
{
return false;
}
lock (objectItemCollection.LoadAssemblyLock)
{
// Check after acquiring the lock, since the known assemblies might have got modified
// Check if the assembly is already loaded. The reason we need to check if the assembly is already loaded, is that
if (objectItemCollection._knownAssemblies.TryGetValue(assembly, out areReferencedAssembliesLoaded))
{
// Proceed if only we need to load the referenced assemblies and they are not loaded
if (loadReferencedAssemblies == false || areReferencedAssembliesLoaded == true)
{
return true;
}
}
Dictionary typesInLoading;
List errors;
Dictionary knownAssemblies;
if (objectItemCollection != null)
{
knownAssemblies = new Dictionary(objectItemCollection._knownAssemblies);
}
else
{
knownAssemblies = new Dictionary();
}
// Load the assembly from the cache
AssemblyCacheEntry.LoadAssemblyFromCache(assembly, loadReferencedAssemblies, knownAssemblies, out typesInLoading, out errors);
// Throw if we have encountered errors
if (errors.Count != 0)
{
throw EntityUtil.InvalidSchemaEncountered(Helper.CombineErrorMessage(errors));
}
// We can encounter new assemblies, but they may not have any time in them
if (typesInLoading.Count != 0)
{
Debug.Assert(knownAssemblies.Count != objectItemCollection._knownAssemblies.Count,
"Since there are no types loaded, some assemblies must have got loaded");
// No errors, so go ahead and add the types and make them readonly
// The existence of the loading lock tells us whether we should be thread safe or not, if we need
// to be thread safe, then we need to use AtomicAddRange. We don't need to actually use the lock
// because the caller should have done it already
// Recheck the assemblies added, another list is created just to match up the collection type
// taken in by AtomicAddRange()
List globalItems = new List();
foreach (EdmType edmType in typesInLoading.Values)
{
globalItems.Add(edmType);
try
{
// Also populate the ocmapping information
if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind)
{
objectItemCollection._ocMapping.Add(((ClrEntityType)edmType).CSpaceTypeName, edmType);
}
else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
{
objectItemCollection._ocMapping.Add(((ClrComplexType)edmType).CSpaceTypeName, edmType);
}
// for rest of the types like relationship type, we do not have oc mapping, so we don't keep
// to keep that information
}
catch (ArgumentException e)
{
throw new MappingException(Strings.Mapping_CannotMapCLRTypeMultipleTimes(edmType.Identity), e);
}
}
// Create a new ObjectItemCollection and add all the global items to it.
// Also copy all the existing items from the existing collection
objectItemCollection.AtomicAddRange(globalItems);
// Update the value of known assemblies
objectItemCollection._knownAssemblies = knownAssemblies;
foreach (Assembly loadedAssembly in knownAssemblies.Keys)
{
CollectIfViewGenAssembly(loadedAssembly);
}
}
}
return true;
}
///
/// Check to see if the assembly has the custom view generation attribute AND
/// collect the assembly into the local list if it has cutom attribute.
///
///
///
private static void CollectIfViewGenAssembly(Assembly assembly)
{
if (assembly.IsDefined(typeof(System.Data.Mapping.EntityViewGenerationAttribute), false /*inherit*/))
{
if (!AssemblyCacheEntry.ViewGenerationAssemblies.Contains(assembly))
{
AssemblyCacheEntry.ViewGenerationAssemblies.Add(assembly);
}
}
}
///
/// Get the list of primitive types for the given space
///
///
public IEnumerable GetPrimitiveTypes()
{
return _primitiveTypeMaps.GetTypes();
}
///
/// The method returns the underlying CLR type for the specified OSpace type argument.
/// If the DataSpace of the parameter is not OSpace, an ArgumentException is thrown.
///
/// The OSpace type to look up
/// The CLR type of the OSpace argument
public Type GetClrType(StructuralType objectSpaceType)
{
Type clrType;
if (!this.TryGetClrType(objectSpaceType, out clrType))
{
throw EntityUtil.Argument(Strings.FailedToFindClrTypeMapping(objectSpaceType.Identity));
}
return clrType;
}
///
/// The method returns the underlying CLR type for the specified OSpace type argument.
/// If the DataSpace of the parameter is not OSpace, the method returns false and sets
/// the out parameter to null.
///
/// The OSpace type to look up
/// The CLR type of the OSpace argument
/// true on success, false on failure
public bool TryGetClrType(StructuralType objectSpaceType, out Type clrType)
{
EntityUtil.CheckArgumentNull(objectSpaceType, "objectSpaceType");
if (objectSpaceType.DataSpace != DataSpace.OSpace)
{
throw EntityUtil.Argument(Strings.ArgumentMustBeOSpaceType, "objectSpaceType");
}
clrType = null;
if (BuiltInTypeKind.EntityType == objectSpaceType.BuiltInTypeKind)
{
clrType = ((ClrEntityType)objectSpaceType).ClrType;
}
else
if (BuiltInTypeKind.ComplexType == objectSpaceType.BuiltInTypeKind)
{
clrType = ((ClrComplexType)objectSpaceType).ClrType;
}
return clrType != null;
}
///
/// Given the canonical primitive type, get the mapping primitive type in the given dataspace
///
/// canonical primitive type
/// The mapped scalar type
internal override PrimitiveType GetMappedPrimitiveType(PrimitiveTypeKind modelType)
{
PrimitiveType type = null;
_primitiveTypeMaps.TryGetType(modelType, null, out type);
return type;
}
///
/// Get the OSpace type given the CSpace typename
///
///
///
///
///
internal bool TryGetOSpaceType(EdmType cspaceType, out EdmType edmType)
{
Debug.Assert(DataSpace.CSpace == cspaceType.DataSpace, "DataSpace should be CSpace");
// check if there is an entity or complex type mapping with this name
if (BuiltInTypeKind.EntityType == cspaceType.BuiltInTypeKind ||
BuiltInTypeKind.ComplexType == cspaceType.BuiltInTypeKind)
{
return _ocMapping.TryGetValue(cspaceType.Identity, out edmType);
}
return TryGetItem(cspaceType.Identity, out edmType);
}
///
/// Given the ospace type, returns the fullname of the mapped cspace type.
/// Today, since we allow non-default mapping between entity type and complex type,
/// this is only possible for entity and complex type.
///
///
///
internal static string TryGetMappingCSpaceTypeIdentity(EdmType edmType)
{
Debug.Assert(DataSpace.OSpace == edmType.DataSpace, "DataSpace must be OSpace");
if (BuiltInTypeKind.EntityType == edmType.BuiltInTypeKind)
{
return ((ClrEntityType)edmType).CSpaceTypeName;
}
else if (BuiltInTypeKind.ComplexType == edmType.BuiltInTypeKind)
{
return ((ClrComplexType)edmType).CSpaceTypeName;
}
return edmType.Identity;
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EventHandlerService.cs
- DetailsViewPagerRow.cs
- ErrorEventArgs.cs
- sqlstateclientmanager.cs
- CacheForPrimitiveTypes.cs
- SQLDouble.cs
- TemplatedAdorner.cs
- CorrelationManager.cs
- SqlUtils.cs
- RequestCachePolicy.cs
- LinqDataSourceDeleteEventArgs.cs
- RequestCachingSection.cs
- TableHeaderCell.cs
- SizeFConverter.cs
- Transactions.cs
- XsdBuilder.cs
- CryptoProvider.cs
- _StreamFramer.cs
- FileLevelControlBuilderAttribute.cs
- CodeChecksumPragma.cs
- SqlVisitor.cs
- HMAC.cs
- PropertyGridView.cs
- EndpointDispatcherTable.cs
- XmlDataSource.cs
- RuntimeTrackingProfile.cs
- RequestChannelBinder.cs
- ByteAnimation.cs
- GotoExpression.cs
- ParseNumbers.cs
- DataSvcMapFileSerializer.cs
- EntityDataSourceDataSelectionPanel.cs
- Compiler.cs
- ReferenceConverter.cs
- HtmlTableCell.cs
- PersonalizationEntry.cs
- ChannelSinkStacks.cs
- ConfigXmlDocument.cs
- CommandID.cs
- ToolStripDesignerUtils.cs
- EDesignUtil.cs
- Vector3DCollectionValueSerializer.cs
- OutOfProcStateClientManager.cs
- TabPanel.cs
- GridViewHeaderRowPresenter.cs
- OleDbCommandBuilder.cs
- Native.cs
- CellParagraph.cs
- DataGridViewBand.cs
- GridView.cs
- ReadOnlyDictionary.cs
- EarlyBoundInfo.cs
- tibetanshape.cs
- __Error.cs
- SqlDataSourceView.cs
- NetNamedPipeSecurity.cs
- ThreadStaticAttribute.cs
- GB18030Encoding.cs
- BoundColumn.cs
- Emitter.cs
- SpeechSynthesizer.cs
- TypedElement.cs
- WsdlBuildProvider.cs
- counter.cs
- TimeEnumHelper.cs
- SafeFileMappingHandle.cs
- XamlParser.cs
- DynamicPropertyHolder.cs
- HttpApplicationStateWrapper.cs
- GridLength.cs
- DoubleConverter.cs
- GroupDescription.cs
- Label.cs
- ServicesUtilities.cs
- TreeNode.cs
- WmlPanelAdapter.cs
- Compiler.cs
- XamlStream.cs
- BitmapSizeOptions.cs
- HtmlPageAdapter.cs
- InputBinder.cs
- PageCatalogPart.cs
- EntryPointNotFoundException.cs
- WebPartConnectionsDisconnectVerb.cs
- Error.cs
- SupportsPreviewControlAttribute.cs
- HtmlGenericControl.cs
- TransformValueSerializer.cs
- SplitterPanelDesigner.cs
- storepermissionattribute.cs
- DesigntimeLicenseContextSerializer.cs
- HttpProtocolImporter.cs
- ThemeDictionaryExtension.cs
- ScriptingSectionGroup.cs
- ProgressPage.cs
- RemoteWebConfigurationHostServer.cs
- LogEntryUtils.cs
- KnownAssemblyEntry.cs
- CodeConstructor.cs
- XmlEncodedRawTextWriter.cs