Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@ -0,0 +1,425 @@
//---------------------------------------------------------------------
// <copyright file="BaseMetadataMappingVisitor.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Metadata.Edm;
using System.Data.Common;
using System.Data.Common.Utils;
using System.Data.Mapping;
using System.Diagnostics;
using System.Globalization;
namespace System.Data.Mapping
{
internal abstract class BaseMetadataMappingVisitor
{
protected BaseMetadataMappingVisitor()
{
}
protected virtual void Visit(StorageEntityContainerMapping storageEntityContainerMapping)
{
Visit(storageEntityContainerMapping.EdmEntityContainer);
Visit(storageEntityContainerMapping.StorageEntityContainer);
foreach (var mapping in storageEntityContainerMapping.EntitySetMaps)
{
Visit(mapping);
}
}
protected virtual void Visit(EntitySetBase entitySetBase)
{
// this is a switching node, so no object header and footer will be add for this node,
// also this Visit won't add the object to the seen list
switch (entitySetBase.BuiltInTypeKind)
{
case BuiltInTypeKind.EntitySet:
Visit((EntitySet)entitySetBase);
break;
case BuiltInTypeKind.AssociationSet:
Visit((AssociationSet)entitySetBase);
break;
default:
Debug.Fail(string.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", entitySetBase.BuiltInTypeKind));
break;
}
}
protected virtual void Visit(StorageSetMapping storageSetMapping)
{
foreach (var typeMapping in storageSetMapping.TypeMappings)
{
Visit(typeMapping);
}
Visit(storageSetMapping.EntityContainerMapping);
}
protected virtual void Visit(EntityContainer entityContainer)
{
foreach (var set in entityContainer.BaseEntitySets)
{
Visit(set);
}
}
protected virtual void Visit(EntitySet entitySet)
{
Visit(entitySet.ElementType);
Visit(entitySet.EntityContainer);
}
protected virtual void Visit(AssociationSet associationSet)
{
Visit(associationSet.ElementType);
Visit(associationSet.EntityContainer);
foreach (var end in associationSet.AssociationSetEnds)
{
Visit(end);
}
}
protected virtual void Visit(EntityType entityType)
{
foreach (var kmember in entityType.KeyMembers)
{
Visit(kmember);
}
foreach (var member in entityType.GetDeclaredOnlyMembers<EdmMember>())
{
Visit(member);
}
foreach (var nproperty in entityType.NavigationProperties)
{
Visit(nproperty);
}
foreach (var property in entityType.Properties)
{
Visit(property);
}
}
protected virtual void Visit(AssociationType associationType)
{
foreach (var endMember in associationType.AssociationEndMembers)
{
Visit(endMember);
}
Visit(associationType.BaseType);
foreach (var keyMember in associationType.KeyMembers)
{
Visit(keyMember);
}
foreach (var member in associationType.GetDeclaredOnlyMembers<EdmMember>())
{
Visit(member);
}
foreach (var item in associationType.ReferentialConstraints)
{
Visit(item);
}
foreach (var item in associationType.RelationshipEndMembers)
{
Visit(item);
}
}
protected virtual void Visit(AssociationSetEnd associationSetEnd)
{
Visit(associationSetEnd.CorrespondingAssociationEndMember);
Visit(associationSetEnd.EntitySet);
Visit(associationSetEnd.ParentAssociationSet);
}
protected virtual void Visit(EdmProperty edmProperty)
{
Visit(edmProperty.TypeUsage);
}
protected virtual void Visit(NavigationProperty navigationProperty)
{
Visit(navigationProperty.FromEndMember);
Visit(navigationProperty.RelationshipType);
Visit(navigationProperty.ToEndMember);
Visit(navigationProperty.TypeUsage);
}
protected virtual void Visit(EdmMember edmMember)
{
Visit(edmMember.TypeUsage);
}
protected virtual void Visit(AssociationEndMember associationEndMember)
{
Visit(associationEndMember.TypeUsage);
}
protected virtual void Visit(ReferentialConstraint referentialConstraint)
{
foreach (var property in referentialConstraint.FromProperties)
{
Visit(property);
}
Visit(referentialConstraint.FromRole);
foreach (var property in referentialConstraint.ToProperties)
{
Visit(property);
}
Visit(referentialConstraint.ToRole);
}
protected virtual void Visit(RelationshipEndMember relationshipEndMember)
{
Visit(relationshipEndMember.TypeUsage);
}
protected virtual void Visit(TypeUsage typeUsage)
{
Visit(typeUsage.EdmType);
foreach (var facet in typeUsage.Facets)
{
Visit(facet);
}
}
protected virtual void Visit(RelationshipType relationshipType)
{
// switching node, will not be add to the seen list
if (relationshipType == null)
{
return;
}
#region Inner data visit
switch (relationshipType.BuiltInTypeKind)
{
case BuiltInTypeKind.AssociationType:
Visit((AssociationType)relationshipType);
break;
default:
Debug.Fail(String.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", relationshipType.BuiltInTypeKind));
break;
}
#endregion
}
protected virtual void Visit(EdmType edmType)
{
// switching node, will not be add to the seen list
if (edmType == null)
{
return;
}
#region Inner data visit
switch (edmType.BuiltInTypeKind)
{
case BuiltInTypeKind.EntityType:
Visit((EntityType)edmType);
break;
case BuiltInTypeKind.AssociationType:
Visit((AssociationType)edmType);
break;
case BuiltInTypeKind.EdmFunction:
Visit((EdmFunction)edmType);
break;
case BuiltInTypeKind.ComplexType:
Visit((ComplexType)edmType);
break;
case BuiltInTypeKind.PrimitiveType:
Visit((PrimitiveType)edmType);
break;
case BuiltInTypeKind.RefType:
Visit((RefType)edmType);
break;
case BuiltInTypeKind.CollectionType:
Visit((CollectionType)edmType);
break;
case BuiltInTypeKind.EnumType:
Visit((EnumType)edmType);
break;
default:
Debug.Fail(String.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", edmType.BuiltInTypeKind));
break;
}
#endregion
}
protected virtual void Visit(Facet facet)
{
Visit(facet.FacetType);
}
protected virtual void Visit(EdmFunction edmFunction)
{
Visit(edmFunction.BaseType);
foreach (var entitySet in edmFunction.EntitySets)
{
if (entitySet != null)
{
Visit(entitySet);
}
}
foreach (var functionParameter in edmFunction.Parameters)
{
Visit(functionParameter);
}
foreach (var returnParameter in edmFunction.ReturnParameters)
{
Visit(returnParameter);
}
}
protected virtual void Visit(PrimitiveType primitiveType)
{
}
protected virtual void Visit(ComplexType complexType)
{
Visit(complexType.BaseType);
foreach (var member in complexType.Members)
{
Visit(member);
}
foreach (var property in complexType.Properties)
{
Visit(property);
}
}
protected virtual void Visit(RefType refType)
{
Visit(refType.BaseType);
Visit(refType.ElementType);
}
protected virtual void Visit(EnumType enumType)
{
foreach (var member in enumType.Members)
{
Visit(member);
}
}
protected virtual void Visit(EnumMember enumMember)
{
}
protected virtual void Visit(CollectionType collectionType)
{
Visit(collectionType.BaseType);
Visit(collectionType.TypeUsage);
}
protected virtual void Visit(EntityTypeBase entityTypeBase)
{
// switching node
if (entityTypeBase == null)
{
return;
}
switch (entityTypeBase.BuiltInTypeKind)
{
case BuiltInTypeKind.AssociationType:
Visit((AssociationType)entityTypeBase);
break;
case BuiltInTypeKind.EntityType:
Visit((EntityType)entityTypeBase);
break;
default:
Debug.Fail(String.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", entityTypeBase.BuiltInTypeKind));
break;
}
}
protected virtual void Visit(FunctionParameter functionParameter)
{
Visit(functionParameter.DeclaringFunction);
Visit(functionParameter.TypeUsage);
}
protected virtual void Visit(DbProviderManifest providerManifest)
{
}
protected virtual void Visit(StorageTypeMapping storageTypeMapping)
{
foreach (var type in storageTypeMapping.IsOfTypes)
{
Visit(type);
}
foreach (var fragment in storageTypeMapping.MappingFragments)
{
Visit(fragment);
}
Visit(storageTypeMapping.SetMapping);
foreach (var type in storageTypeMapping.Types)
{
Visit(type);
}
}
protected virtual void Visit(StorageMappingFragment storageMappingFragment)
{
foreach (var property in storageMappingFragment.AllProperties)
{
Visit(property);
}
Visit((EntitySetBase)storageMappingFragment.TableSet);
}
protected virtual void Visit(StoragePropertyMapping storagePropertyMapping)
{
// this is a switching node, so no object header and footer will be add for this node,
// also this Visit won't add the object to the seen list
if (storagePropertyMapping.GetType() == typeof(StorageComplexPropertyMapping))
{
Visit((StorageComplexPropertyMapping)storagePropertyMapping);
}
else if (storagePropertyMapping.GetType() == typeof(StorageConditionPropertyMapping))
{
Visit((StorageConditionPropertyMapping)storagePropertyMapping);
}
else if (storagePropertyMapping.GetType() == typeof(StorageScalarPropertyMapping))
{
Visit((StorageScalarPropertyMapping)storagePropertyMapping);
}
else
{
Debug.Fail(String.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", storagePropertyMapping.GetType()));
}
}
protected virtual void Visit(StorageComplexPropertyMapping storageComplexPropertyMapping)
{
Visit(storageComplexPropertyMapping.EdmProperty);
foreach (var mapping in storageComplexPropertyMapping.TypeMappings)
{
Visit(mapping);
}
}
protected virtual void Visit(StorageConditionPropertyMapping storageConditionPropertyMapping)
{
Visit(storageConditionPropertyMapping.ColumnProperty);
Visit(storageConditionPropertyMapping.EdmProperty);
}
protected virtual void Visit(StorageScalarPropertyMapping storageScalarPropertyMapping)
{
Visit(storageScalarPropertyMapping.ColumnProperty);
Visit(storageScalarPropertyMapping.EdmProperty);
}
protected virtual void Visit(StorageComplexTypeMapping storageComplexTypeMapping)
{
foreach (var property in storageComplexTypeMapping.AllProperties)
{
Visit(property);
}
foreach (var type in storageComplexTypeMapping.IsOfTypes)
{
Visit(type);
}
foreach (var type in storageComplexTypeMapping.Types)
{
Visit(type);
}
}
}
}

View File

@ -0,0 +1,109 @@
//---------------------------------------------------------------------
// <copyright file="EntityViewContainer.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common.Utils;
using System.Text;
namespace System.Data.Mapping
{
/// <summary>
/// Base class for the type created at design time to store the generated views.
/// </summary>
public abstract class EntityViewContainer
{
#region Constructors
protected EntityViewContainer()
{
}
#endregion
#region fields
private string m_storedHashOverMappingClosure; // Hash value over the whole Metadata and Mapping closure
private string m_storedhashOverAllExtentViews; // Hash value over all the extent views
private string m_storededmEntityContainerName; // C side entity container name
private string m_storedStoreEntityContainerName; // S side entity container name
private int _viewCount;
#endregion
#region properties
/// <summary>
/// Returns the cached dictionary of (ExtentName,EsqlView)
/// </summary>
internal IEnumerable<KeyValuePair<string, string>> ExtentViews
{
get
{
for (int i = 0; i < ViewCount; i++)
{
yield return GetViewAt(i);
}
}
}
protected abstract System.Collections.Generic.KeyValuePair<string, string> GetViewAt(int index);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")]
public string EdmEntityContainerName
{
get
{
return this.m_storededmEntityContainerName;
}
set
{
this.m_storededmEntityContainerName = value;
}
}
public string StoreEntityContainerName
{
get
{
return this.m_storedStoreEntityContainerName;
}
set
{
this.m_storedStoreEntityContainerName = value;
}
}
public string HashOverMappingClosure
{
get
{
return this.m_storedHashOverMappingClosure;
}
set
{
this.m_storedHashOverMappingClosure = value;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "OverAll")]
public string HashOverAllExtentViews
{
get
{
return this.m_storedhashOverAllExtentViews;
}
set
{
this.m_storedhashOverAllExtentViews = value;
}
}
public int ViewCount
{
get { return _viewCount; }
protected set { _viewCount = value; }
}
#endregion
}
}

View File

@ -0,0 +1,42 @@
//---------------------------------------------------------------------
// <copyright file="EntityViewGenerationAttribute.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
namespace System.Data.Mapping
{
/// <summary>
/// Attribute to mark the assemblies that contain the generated views type.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class EntityViewGenerationAttribute : System.Attribute
{
#region Constructors
/// <summary>
/// Constructor for EntityViewGenerationAttribute
/// </summary>
public EntityViewGenerationAttribute(Type viewGenerationType)
{
EntityUtil.CheckArgumentNull<Type>(viewGenerationType, "viewGenType");
m_viewGenType = viewGenerationType;
}
#endregion
#region Fields
private Type m_viewGenType;
#endregion
#region Properties
public Type ViewGenerationType
{
get { return m_viewGenType; }
}
#endregion
}
}

View File

@ -0,0 +1,290 @@
//---------------------------------------------------------------------
// <copyright file="FunctionImportMapping.ReturnTypeRanameMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Metadata.Edm;
using System.Data.Common.Utils;
using System.Xml;
using System.Collections.ObjectModel;
using System.Diagnostics;
namespace System.Data.Mapping
{
internal abstract class FunctionImportStructuralTypeMapping
{
internal readonly LineInfo LineInfo;
internal readonly Collection<FunctionImportReturnTypePropertyMapping> ColumnsRenameList;
internal FunctionImportStructuralTypeMapping(Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList, LineInfo lineInfo)
{
this.ColumnsRenameList = columnsRenameList;
this.LineInfo = lineInfo;
}
}
internal sealed class FunctionImportEntityTypeMapping : FunctionImportStructuralTypeMapping
{
internal FunctionImportEntityTypeMapping(IEnumerable<EntityType> isOfTypeEntityTypes,
IEnumerable<EntityType> entityTypes, IEnumerable<FunctionImportEntityTypeMappingCondition> conditions,
Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList,
LineInfo lineInfo)
: base(columnsRenameList, lineInfo)
{
this.IsOfTypeEntityTypes = new ReadOnlyCollection<EntityType>(
EntityUtil.CheckArgumentNull(isOfTypeEntityTypes, "isOfTypeEntityTypes").ToList());
this.EntityTypes = new ReadOnlyCollection<EntityType>(
EntityUtil.CheckArgumentNull(entityTypes, "entityTypes").ToList());
this.Conditions = new ReadOnlyCollection<FunctionImportEntityTypeMappingCondition>(
EntityUtil.CheckArgumentNull(conditions, "conditions").ToList());
}
internal readonly ReadOnlyCollection<FunctionImportEntityTypeMappingCondition> Conditions;
internal readonly ReadOnlyCollection<EntityType> EntityTypes;
internal readonly ReadOnlyCollection<EntityType> IsOfTypeEntityTypes;
/// <summary>
/// Gets all (concrete) entity types implied by this type mapping.
/// </summary>
internal IEnumerable<EntityType> GetMappedEntityTypes(ItemCollection itemCollection)
{
const bool includeAbstractTypes = false;
return this.EntityTypes.Concat(
this.IsOfTypeEntityTypes.SelectMany(entityType =>
MetadataHelper.GetTypeAndSubtypesOf(entityType, itemCollection, includeAbstractTypes)
.Cast<EntityType>()));
}
internal IEnumerable<String> GetDiscriminatorColumns()
{
return this.Conditions.Select(condition => condition.ColumnName);
}
}
internal sealed class FunctionImportComplexTypeMapping : FunctionImportStructuralTypeMapping
{
internal readonly ComplexType ReturnType;
internal FunctionImportComplexTypeMapping(ComplexType returnType, Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList, LineInfo lineInfo)
: base(columnsRenameList, lineInfo)
{
this.ReturnType = returnType;
}
}
internal abstract class FunctionImportReturnTypePropertyMapping
{
internal readonly string CMember;
internal readonly string SColumn;
internal readonly LineInfo LineInfo;
internal FunctionImportReturnTypePropertyMapping(string cMember, string sColumn, LineInfo lineInfo)
{
this.CMember = cMember;
this.SColumn = sColumn;
this.LineInfo = lineInfo;
}
}
internal sealed class FunctionImportReturnTypeScalarPropertyMapping : FunctionImportReturnTypePropertyMapping
{
internal FunctionImportReturnTypeScalarPropertyMapping(string cMember, string sColumn, LineInfo lineInfo)
: base(cMember, sColumn, lineInfo)
{
}
}
/// <summary>
/// extract the column rename info from polymorphic entity type mappings
/// </summary>
internal sealed class FunctionImportReturnTypeEntityTypeColumnsRenameBuilder
{
/// <summary>
/// CMember -> SMember*
/// </summary>
internal Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> ColumnRenameMapping;
internal FunctionImportReturnTypeEntityTypeColumnsRenameBuilder(
Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>> isOfTypeEntityTypeColumnsRenameMapping,
Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>> entityTypeColumnsRenameMapping)
{
EntityUtil.CheckArgumentNull(isOfTypeEntityTypeColumnsRenameMapping, "isOfTypeEntityTypeColumnsRenameMapping");
EntityUtil.CheckArgumentNull(entityTypeColumnsRenameMapping, "entityTypeColumnsRenameMapping");
this.ColumnRenameMapping = new Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
// Assign the columns renameMapping to the result dictionary.
foreach (EntityType entityType in isOfTypeEntityTypeColumnsRenameMapping.Keys)
{
this.SetStructuralTypeColumnsRename(
entityType, isOfTypeEntityTypeColumnsRenameMapping[entityType], true/*isTypeOf*/);
}
foreach (EntityType entityType in entityTypeColumnsRenameMapping.Keys)
{
this.SetStructuralTypeColumnsRename(
entityType, entityTypeColumnsRenameMapping[entityType], false/*isTypeOf*/);
}
}
/// <summary>
/// Set the column mappings for each defaultMemberName.
/// </summary>
private void SetStructuralTypeColumnsRename(
EntityType entityType,
Collection<FunctionImportReturnTypePropertyMapping> columnsRenameMapping,
bool isTypeOf)
{
EntityUtil.CheckArgumentNull(entityType, "entityType");
EntityUtil.CheckArgumentNull(columnsRenameMapping, "columnsRenameMapping");
foreach (var mapping in columnsRenameMapping)
{
if (!this.ColumnRenameMapping.Keys.Contains(mapping.CMember))
{
this.ColumnRenameMapping[mapping.CMember] = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(mapping.CMember);
}
this.ColumnRenameMapping[mapping.CMember].AddRename(new FunctionImportReturnTypeStructuralTypeColumn(mapping.SColumn, entityType, isTypeOf, mapping.LineInfo));
}
}
}
internal sealed class FunctionImportReturnTypeStructuralTypeColumn
{
internal readonly StructuralType Type;
internal readonly bool IsTypeOf;
internal readonly string ColumnName;
internal readonly LineInfo LineInfo;
internal FunctionImportReturnTypeStructuralTypeColumn(string columnName, StructuralType type, bool isTypeOf, LineInfo lineInfo)
{
this.ColumnName = columnName;
this.IsTypeOf = isTypeOf;
this.Type = type;
this.LineInfo = lineInfo;
}
}
internal class FunctionImportReturnTypeStructuralTypeColumnRenameMapping
{
private Collection<FunctionImportReturnTypeStructuralTypeColumn> _columnListForType;
private Collection<FunctionImportReturnTypeStructuralTypeColumn> _columnListForIsTypeOfType;
/// <summary>
/// Null if default mapping is not allowed.
/// </summary>
private readonly string _defaultMemberName;
private Memoizer<StructuralType, FunctionImportReturnTypeStructuralTypeColumn> _renameCache;
internal FunctionImportReturnTypeStructuralTypeColumnRenameMapping(string defaultMemberName)
{
this._defaultMemberName = defaultMemberName;
this._columnListForType = new Collection<FunctionImportReturnTypeStructuralTypeColumn>();
this._columnListForIsTypeOfType = new Collection<FunctionImportReturnTypeStructuralTypeColumn>();
this._renameCache = new Memoizer<StructuralType, FunctionImportReturnTypeStructuralTypeColumn>(
this.GetRename, EqualityComparer<StructuralType>.Default);
}
/// <summary>
/// <see cref="GetRename(EdmType, out IXmlLineInfo)"/> for more info.
/// </summary>
internal string GetRename(EdmType type)
{
IXmlLineInfo lineInfo;
return GetRename(type, out lineInfo);
}
/// <summary>
/// A default mapping (property "Foo" maps by convention to column "Foo"), if allowed, has the lowest precedence.
/// A mapping for a specific type (EntityType="Bar") takes precedence over a mapping for a hierarchy (EntityType="IsTypeOf(Bar)"))
/// If there are two hierarchy mappings, the most specific mapping takes precedence.
/// For instance, given the types Base, Derived1 : Base, and Derived2 : Derived1,
/// w.r.t. Derived1 "IsTypeOf(Derived1)" takes precedence over "IsTypeOf(Base)" when you ask for the rename of Derived1
/// </summary>
/// <param name="lineInfo">Empty for default rename mapping.</param>
internal string GetRename(EdmType type, out IXmlLineInfo lineInfo)
{
Debug.Assert(type is StructuralType, "we can only rename structural type");
EntityUtil.CheckArgumentNull(type, "type");
var rename = this._renameCache.Evaluate(type as StructuralType);
lineInfo = rename.LineInfo;
return rename.ColumnName;
}
private FunctionImportReturnTypeStructuralTypeColumn GetRename(StructuralType typeForRename)
{
FunctionImportReturnTypeStructuralTypeColumn ofTypecolumn = _columnListForType.FirstOrDefault(t => t.Type == typeForRename);
if (null != ofTypecolumn)
{
return ofTypecolumn;
}
// if there are duplicate istypeof mapping defined rename for the same column, the last one wins
FunctionImportReturnTypeStructuralTypeColumn isOfTypeColumn = _columnListForIsTypeOfType.Where(t => t.Type == typeForRename).LastOrDefault();
if (null != isOfTypeColumn)
{
return isOfTypeColumn;
}
else
{
// find out all the tyes that is isparent type of this lookup type
IEnumerable<FunctionImportReturnTypeStructuralTypeColumn> nodesInBaseHierachy =
_columnListForIsTypeOfType.Where(t => t.Type.IsAssignableFrom(typeForRename));
if (nodesInBaseHierachy.Count() == 0)
{
// non of its parent is renamed, so it will take the default one
return new FunctionImportReturnTypeStructuralTypeColumn(this._defaultMemberName, typeForRename, false, null);
}
else
{
// we will guarantee that there will be some mapping for us on this column
// find out which one is lowest on the link
return GetLowestParentInHierachy(nodesInBaseHierachy);
}
}
}
private FunctionImportReturnTypeStructuralTypeColumn GetLowestParentInHierachy(IEnumerable<FunctionImportReturnTypeStructuralTypeColumn> nodesInHierachy)
{
FunctionImportReturnTypeStructuralTypeColumn lowestParent = null;
foreach (var node in nodesInHierachy)
{
if (lowestParent == null)
{
lowestParent = node;
}
else if (lowestParent.Type.IsAssignableFrom(node.Type))
{
lowestParent = node;
}
}
Debug.Assert(null != lowestParent, "We should have the lowest parent");
return lowestParent;
}
internal void AddRename(FunctionImportReturnTypeStructuralTypeColumn renamedColumn)
{
EntityUtil.CheckArgumentNull(renamedColumn, "renamedColumn");
if (!renamedColumn.IsTypeOf)
{
// add to collection if the mapping is for specific type
this._columnListForType.Add(renamedColumn);
}
else
{
_columnListForIsTypeOfType.Add(renamedColumn);
}
}
}
}

View File

@ -0,0 +1,470 @@
//---------------------------------------------------------------------
// <copyright file="FunctionImportMappingComposable.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner willa
//---------------------------------------------------------------------
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Common.CommandTrees;
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Data.Common.Utils;
using System.Data.Mapping.ViewGeneration;
using System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
using System.Data.Query.PlanCompiler;
using System.Diagnostics;
using System.Linq;
namespace System.Data.Mapping
{
/// <summary>
/// Represents a mapping from a model function import to a store composable function.
/// </summary>
internal class FunctionImportMappingComposable : FunctionImportMapping
{
#region Constructors
internal FunctionImportMappingComposable(
EdmFunction functionImport,
EdmFunction targetFunction,
List<Tuple<StructuralType, List<StorageConditionPropertyMapping>, List<StoragePropertyMapping>>> structuralTypeMappings,
EdmProperty[] targetFunctionKeys,
StorageMappingItemCollection mappingItemCollection,
string sourceLocation,
LineInfo lineInfo)
: base(functionImport, targetFunction)
{
EntityUtil.CheckArgumentNull(mappingItemCollection, "mappingItemCollection");
Debug.Assert(functionImport.IsComposableAttribute, "functionImport.IsComposableAttribute");
Debug.Assert(targetFunction.IsComposableAttribute, "targetFunction.IsComposableAttribute");
Debug.Assert(functionImport.EntitySet == null || structuralTypeMappings != null, "Function import returning entities must have structuralTypeMappings.");
Debug.Assert(structuralTypeMappings == null || structuralTypeMappings.Count > 0, "Non-null structuralTypeMappings must not be empty.");
EdmType resultType;
Debug.Assert(
structuralTypeMappings != null ||
MetadataHelper.TryGetFunctionImportReturnType<EdmType>(functionImport, 0, out resultType) && TypeSemantics.IsScalarType(resultType),
"Either type mappings should be specified or the function import should be Collection(Scalar).");
Debug.Assert(functionImport.EntitySet == null || targetFunctionKeys != null, "Keys must be inferred for a function import returning entities.");
Debug.Assert(targetFunctionKeys == null || targetFunctionKeys.Length > 0, "Keys must be null or non-empty.");
m_mappingItemCollection = mappingItemCollection;
// We will use these parameters to target s-space function calls in the generated command tree.
// Since enums don't exist in s-space we need to use the underlying type.
m_commandParameters = functionImport.Parameters.Select(p => TypeHelpers.GetPrimitiveTypeUsageForScalar(p.TypeUsage).Parameter(p.Name)).ToArray();
m_structuralTypeMappings = structuralTypeMappings;
m_targetFunctionKeys = targetFunctionKeys;
m_sourceLocation = sourceLocation;
m_lineInfo = lineInfo;
}
#endregion
#region Fields
private readonly StorageMappingItemCollection m_mappingItemCollection;
/// <summary>
/// Command parameter refs created from m_edmFunction parameters.
/// Used as arguments to target (s-space) function calls in the generated command tree.
/// </summary>
private readonly DbParameterReferenceExpression[] m_commandParameters;
/// <summary>
/// Result mapping as entity type hierarchy.
/// </summary>
private readonly List<Tuple<StructuralType, List<StorageConditionPropertyMapping>, List<StoragePropertyMapping>>> m_structuralTypeMappings;
/// <summary>
/// Keys inside the result set of the target function. Inferred based on the mapping (using c-space entity type keys).
/// </summary>
private readonly EdmProperty[] m_targetFunctionKeys;
/// <summary>
/// ITree template. Requires function argument substitution during function view expansion.
/// </summary>
private Node m_internalTreeNode;
private readonly string m_sourceLocation;
private readonly LineInfo m_lineInfo;
#endregion
#region Properties/Methods
internal EdmProperty[] TvfKeys
{
get { return m_targetFunctionKeys; }
}
#region GetInternalTree(...) implementation
internal Node GetInternalTree(Command targetIqtCommand, IList<Node> targetIqtArguments)
{
if (m_internalTreeNode == null)
{
var viewGenErrors = new List<EdmSchemaError>();
DiscriminatorMap discriminatorMap;
DbQueryCommandTree tree = GenerateFunctionView(viewGenErrors, out discriminatorMap);
if (viewGenErrors.Count > 0)
{
throw new MappingException(Helper.CombineErrorMessage(viewGenErrors));
}
Debug.Assert(tree != null, "tree != null");
// Convert this into an ITree first
Command itree = ITreeGenerator.Generate(tree, discriminatorMap);
var rootProject = itree.Root; // PhysicalProject(RelInput)
PlanCompiler.Assert(rootProject.Op.OpType == OpType.PhysicalProject, "Expected a physical projectOp at the root of the tree - found " + rootProject.Op.OpType);
var rootProjectOp = (PhysicalProjectOp)rootProject.Op;
Debug.Assert(rootProjectOp.Outputs.Count == 1, "rootProjectOp.Outputs.Count == 1");
var rootInput = rootProject.Child0; // the RelInput in PhysicalProject(RelInput)
// #554756: VarVec enumerators are not cached on the shared Command instance.
itree.DisableVarVecEnumCaching();
// Function import returns a collection, so convert it to a scalar by wrapping into CollectOp.
Node relNode = rootInput;
Var relVar = rootProjectOp.Outputs[0];
// ProjectOp does not implement Type property, so get the type from the column map.
TypeUsage functionViewType = rootProjectOp.ColumnMap.Type;
if (!Command.EqualTypes(functionViewType, this.FunctionImport.ReturnParameter.TypeUsage))
{
Debug.Assert(TypeSemantics.IsPromotableTo(functionViewType, this.FunctionImport.ReturnParameter.TypeUsage), "Mapping expression result type must be promotable to the c-space function return type.");
// Build "relNode = Project(relNode, SoftCast(relVar))"
CollectionType expectedCollectionType = (CollectionType)this.FunctionImport.ReturnParameter.TypeUsage.EdmType;
var expectedElementType = expectedCollectionType.TypeUsage;
Node varRefNode = itree.CreateNode(itree.CreateVarRefOp(relVar));
Node castNode = itree.CreateNode(itree.CreateSoftCastOp(expectedElementType), varRefNode);
Node varDefListNode = itree.CreateVarDefListNode(castNode, out relVar);
ProjectOp projectOp = itree.CreateProjectOp(relVar);
relNode = itree.CreateNode(projectOp, relNode, varDefListNode);
}
// Build "Collect(PhysicalProject(relNode))
m_internalTreeNode = itree.BuildCollect(relNode, relVar);
}
Debug.Assert(m_internalTreeNode != null, "m_internalTreeNode != null");
// Prepare argument replacement dictionary
Debug.Assert(m_commandParameters.Length == targetIqtArguments.Count, "m_commandParameters.Length == targetIqtArguments.Count");
Dictionary<string, Node> viewArguments = new Dictionary<string, Node>(m_commandParameters.Length);
for (int i = 0; i < m_commandParameters.Length; ++i)
{
var commandParam = (DbParameterReferenceExpression)m_commandParameters[i];
var argumentNode = targetIqtArguments[i];
// If function import parameter is of enum type, the argument value for it will be of enum type. We however have
// converted enum types to underlying types for m_commandParameters. So we now need to softcast the argument
// expression to the underlying type as well.
if (TypeSemantics.IsEnumerationType(argumentNode.Op.Type))
{
argumentNode = targetIqtCommand.CreateNode(
targetIqtCommand.CreateSoftCastOp(TypeHelpers.CreateEnumUnderlyingTypeUsage(argumentNode.Op.Type)),
argumentNode);
}
Debug.Assert(TypeSemantics.IsPromotableTo(argumentNode.Op.Type, commandParam.ResultType), "Argument type must be promotable to parameter type.");
viewArguments.Add(commandParam.ParameterName, argumentNode);
}
return FunctionViewOpCopier.Copy(targetIqtCommand, m_internalTreeNode, viewArguments);
}
private sealed class FunctionViewOpCopier : OpCopier
{
private Dictionary<string, Node> m_viewArguments;
private FunctionViewOpCopier(Command cmd, Dictionary<string, Node> viewArguments)
: base(cmd)
{
m_viewArguments = viewArguments;
}
internal static Node Copy(Command cmd, Node viewNode, Dictionary<string, Node> viewArguments)
{
return new FunctionViewOpCopier(cmd, viewArguments).CopyNode(viewNode);
}
#region Visitor Members
public override Node Visit(VarRefOp op, Node n)
{
// The original function view has store function calls with arguments represented as command parameter refs.
// We are now replacing command parameter refs with the real argument nodes from the calling tree.
// The replacement is performed in the function view subtree and we search for parameter refs with names
// matching the FunctionImportMapping.FunctionImport parameter names (this is how the command parameters
// have been created in the first place, see m_commandParameters and GetCommandTree(...) for more info).
// The search and replace is not performed on the argument nodes themselves. This is important because it guarantees
// that we are not replacing unrelated (possibly user-defined) parameter refs that accidentally have the matching names.
Node argNode;
if (op.Var.VarType == VarType.Parameter && m_viewArguments.TryGetValue(((ParameterVar)op.Var).ParameterName, out argNode))
{
// Just copy the argNode, do not reapply this visitor. We do not want search and replace inside the argNode. See comment above.
return OpCopier.Copy(m_destCmd, argNode);
}
else
{
return base.Visit(op, n);
}
}
#endregion
}
#endregion
#region GenerateFunctionView(...) implementation
#region GenerateFunctionView
internal DbQueryCommandTree GenerateFunctionView(IList<EdmSchemaError> errors, out DiscriminatorMap discriminatorMap)
{
Debug.Assert(errors != null, "errors != null");
discriminatorMap = null;
// Prepare the direct call of the store function as StoreFunction(@EdmFunc_p1, ..., @EdmFunc_pN).
// Note that function call arguments are command parameters created from the m_edmFunction parameters.
Debug.Assert(this.TargetFunction != null, "this.TargetFunction != null");
DbExpression storeFunctionInvoke = this.TargetFunction.Invoke(GetParametersForTargetFunctionCall());
// Generate the query expression producing c-space result from s-space function call(s).
DbExpression queryExpression;
if (m_structuralTypeMappings != null)
{
queryExpression = GenerateStructuralTypeResultMappingView(storeFunctionInvoke, errors, out discriminatorMap);
Debug.Assert(queryExpression == null ||
TypeSemantics.IsPromotableTo(queryExpression.ResultType, this.FunctionImport.ReturnParameter.TypeUsage),
"TypeSemantics.IsPromotableTo(queryExpression.ResultType, this.FunctionImport.ReturnParameter.TypeUsage)");
}
else
{
queryExpression = GenerateScalarResultMappingView(storeFunctionInvoke);
Debug.Assert(queryExpression == null ||
TypeSemantics.IsEqual(queryExpression.ResultType, this.FunctionImport.ReturnParameter.TypeUsage),
"TypeSemantics.IsEqual(queryExpression.ResultType, this.FunctionImport.ReturnParameter.TypeUsage)");
}
if (queryExpression == null)
{
// In case of errors during view generation, return.
return null;
}
// Generate parameterized command, where command parameters are semantically the c-space function parameters.
return DbQueryCommandTree.FromValidExpression(m_mappingItemCollection.Workspace, TargetPerspective.TargetPerspectiveDataSpace, queryExpression);
}
private IEnumerable<DbExpression> GetParametersForTargetFunctionCall()
{
Debug.Assert(this.FunctionImport.Parameters.Count == m_commandParameters.Length, "this.FunctionImport.Parameters.Count == m_commandParameters.Length");
Debug.Assert(this.TargetFunction.Parameters.Count == m_commandParameters.Length, "this.TargetFunction.Parameters.Count == m_commandParameters.Length");
foreach (var targetParameter in this.TargetFunction.Parameters)
{
Debug.Assert(this.FunctionImport.Parameters.Contains(targetParameter.Name), "this.FunctionImport.Parameters.Contains(targetParameter.Name)");
var functionImportParameter = this.FunctionImport.Parameters.Single(p => p.Name == targetParameter.Name);
yield return m_commandParameters[this.FunctionImport.Parameters.IndexOf(functionImportParameter)];
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
internal void ValidateFunctionView(IList<EdmSchemaError> errors)
{
DiscriminatorMap dm;
GenerateFunctionView(errors, out dm);
}
#endregion
#region GenerateStructuralTypeResultMappingView
private DbExpression GenerateStructuralTypeResultMappingView(DbExpression storeFunctionInvoke, IList<EdmSchemaError> errors, out DiscriminatorMap discriminatorMap)
{
Debug.Assert(m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0, "m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0");
discriminatorMap = null;
// Process explicit structural type mappings. The mapping is based on the direct call of the store function
// wrapped into a projection constructing the mapped structural types.
DbExpression queryExpression = storeFunctionInvoke;
if (m_structuralTypeMappings.Count == 1)
{
var mapping = m_structuralTypeMappings[0];
var type = mapping.Item1;
var conditions = mapping.Item2;
var propertyMappings = mapping.Item3;
if (conditions.Count > 0)
{
queryExpression = queryExpression.Where((row) => GenerateStructuralTypeConditionsPredicate(conditions, row));
}
var binding = queryExpression.BindAs("row");
var entityTypeMappingView = GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable, errors);
if (entityTypeMappingView == null)
{
return null;
}
queryExpression = binding.Project(entityTypeMappingView);
}
else
{
var binding = queryExpression.BindAs("row");
// Make sure type projection is performed over a closed set where each row is guaranteed to produce a known type.
// To do this, filter the store function output using the type conditions.
Debug.Assert(m_structuralTypeMappings.All(m => m.Item2.Count > 0), "In multi-type mapping each type must have conditions.");
List<DbExpression> structuralTypePredicates = m_structuralTypeMappings.Select(m => GenerateStructuralTypeConditionsPredicate(m.Item2, binding.Variable)).ToList();
queryExpression = binding.Filter(Helpers.BuildBalancedTreeInPlace(
structuralTypePredicates.ToArray(), // clone, otherwise BuildBalancedTreeInPlace will change it
(prev, next) => prev.Or(next)));
binding = queryExpression.BindAs("row");
List<DbExpression> structuralTypeMappingViews = new List<DbExpression>(m_structuralTypeMappings.Count);
foreach (var mapping in m_structuralTypeMappings)
{
var type = mapping.Item1;
var propertyMappings = mapping.Item3;
var structuralTypeMappingView = GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable, errors);
if (structuralTypeMappingView == null)
{
continue;
}
else
{
structuralTypeMappingViews.Add(structuralTypeMappingView);
}
}
Debug.Assert(structuralTypeMappingViews.Count == structuralTypePredicates.Count, "structuralTypeMappingViews.Count == structuralTypePredicates.Count");
if (structuralTypeMappingViews.Count != m_structuralTypeMappings.Count)
{
Debug.Assert(errors.Count > 0, "errors.Count > 0");
return null;
}
// Because we are projecting over the closed set, we can convert the last WHEN THEN into ELSE.
DbExpression typeConstructors = DbExpressionBuilder.Case(
structuralTypePredicates.Take(m_structuralTypeMappings.Count - 1),
structuralTypeMappingViews.Take(m_structuralTypeMappings.Count - 1),
structuralTypeMappingViews[m_structuralTypeMappings.Count - 1]);
queryExpression = binding.Project(typeConstructors);
if (DiscriminatorMap.TryCreateDiscriminatorMap(this.FunctionImport.EntitySet, queryExpression, out discriminatorMap))
{
Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created");
}
}
return queryExpression;
}
private DbExpression GenerateStructuralTypeMappingView(StructuralType structuralType, List<StoragePropertyMapping> propertyMappings, DbExpression row, IList<EdmSchemaError> errors)
{
// Generate property views.
var properties = TypeHelpers.GetAllStructuralMembers(structuralType);
Debug.Assert(properties.Count == propertyMappings.Count, "properties.Count == propertyMappings.Count");
var constructorArgs = new List<DbExpression>(properties.Count);
for (int i = 0; i < propertyMappings.Count; ++i)
{
var propertyMapping = propertyMappings[i];
Debug.Assert(properties[i].EdmEquals(propertyMapping.EdmProperty), "properties[i].EdmEquals(propertyMapping.EdmProperty)");
var propertyMappingView = GeneratePropertyMappingView(propertyMapping, row, new List<string>() { propertyMapping.EdmProperty.Name }, errors);
if (propertyMappingView != null)
{
constructorArgs.Add(propertyMappingView);
}
}
if (constructorArgs.Count != propertyMappings.Count)
{
Debug.Assert(errors.Count > 0, "errors.Count > 0");
return null;
}
else
{
// Return the structural type constructor.
return TypeUsage.Create(structuralType).New(constructorArgs);
}
}
private DbExpression GenerateStructuralTypeConditionsPredicate(List<StorageConditionPropertyMapping> conditions, DbExpression row)
{
Debug.Assert(conditions.Count > 0, "conditions.Count > 0");
DbExpression predicate = Helpers.BuildBalancedTreeInPlace(conditions.Select(c => GeneratePredicate(c, row)).ToArray(), (prev, next) => prev.And(next));
return predicate;
}
private DbExpression GeneratePredicate(StorageConditionPropertyMapping condition, DbExpression row)
{
Debug.Assert(condition.EdmProperty == null, "C-side conditions are not supported in function mappings.");
DbExpression columnRef = GenerateColumnRef(row, condition.ColumnProperty);
if (condition.IsNull.HasValue)
{
return condition.IsNull.Value ? (DbExpression)columnRef.IsNull() : (DbExpression)columnRef.IsNull().Not();
}
else
{
return columnRef.Equal(columnRef.ResultType.Constant(condition.Value));
}
}
private DbExpression GeneratePropertyMappingView(StoragePropertyMapping mapping, DbExpression row, List<string> context, IList<EdmSchemaError> errors)
{
Debug.Assert(mapping is StorageScalarPropertyMapping, "Complex property mapping is not supported in function imports.");
var scalarPropertyMapping = (StorageScalarPropertyMapping)mapping;
return GenerateScalarPropertyMappingView(scalarPropertyMapping.EdmProperty, scalarPropertyMapping.ColumnProperty, row);
}
private DbExpression GenerateScalarPropertyMappingView(EdmProperty edmProperty, EdmProperty columnProperty, DbExpression row)
{
DbExpression accessorExpr = GenerateColumnRef(row, columnProperty);
if (!TypeSemantics.IsEqual(accessorExpr.ResultType, edmProperty.TypeUsage))
{
accessorExpr = accessorExpr.CastTo(edmProperty.TypeUsage);
}
return accessorExpr;
}
private DbExpression GenerateColumnRef(DbExpression row, EdmProperty column)
{
Debug.Assert(row.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.RowType, "Input type is expected to be a row type.");
var rowType = (RowType)row.ResultType.EdmType;
Debug.Assert(rowType.Properties.Contains(column.Name), "Column name must be resolvable in the TVF result type.");
return row.Property(column.Name);
}
#endregion
#region GenerateScalarResultMappingView
private DbExpression GenerateScalarResultMappingView(DbExpression storeFunctionInvoke)
{
DbExpression queryExpression = storeFunctionInvoke;
CollectionType functionImportReturnType;
if (!MetadataHelper.TryGetFunctionImportReturnCollectionType(this.FunctionImport, 0, out functionImportReturnType))
{
Debug.Fail("Failed to get the result type of the function import.");
}
Debug.Assert(TypeSemantics.IsCollectionType(queryExpression.ResultType), "Store function must be TVF (collection expected).");
var collectionType = (CollectionType)queryExpression.ResultType.EdmType;
Debug.Assert(TypeSemantics.IsRowType(collectionType.TypeUsage), "Store function must be TVF (collection of rows expected).");
var rowType = (RowType)collectionType.TypeUsage.EdmType;
var column = rowType.Properties[0];
Func<DbExpression, DbExpression> scalarView = (DbExpression row) =>
{
var propertyAccess = row.Property(column);
if (TypeSemantics.IsEqual(functionImportReturnType.TypeUsage, column.TypeUsage))
{
return propertyAccess;
}
else
{
return propertyAccess.CastTo(functionImportReturnType.TypeUsage);
}
};
queryExpression = queryExpression.Select(row => scalarView(row));
return queryExpression;
}
#endregion
#endregion
#endregion
}
}

View File

@ -0,0 +1,232 @@
//---------------------------------------------------------------------
// <copyright file="FunctionImportMappingNonComposable.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner willa
//---------------------------------------------------------------------
namespace System.Data.Mapping
{
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Common.Utils;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Linq;
using OM = System.Collections.ObjectModel;
/// <summary>
/// Represents a mapping from a model function import to a store non-composable function.
/// </summary>
internal sealed class FunctionImportMappingNonComposable : FunctionImportMapping
{
internal FunctionImportMappingNonComposable(
EdmFunction functionImport,
EdmFunction targetFunction,
List<List<FunctionImportStructuralTypeMapping>> structuralTypeMappingsList,
ItemCollection itemCollection)
: base(functionImport, targetFunction)
{
EntityUtil.CheckArgumentNull(structuralTypeMappingsList, "structuralTypeMappingsList");
EntityUtil.CheckArgumentNull(itemCollection, "itemCollection");
Debug.Assert(!functionImport.IsComposableAttribute, "!functionImport.IsComposableAttribute");
Debug.Assert(!targetFunction.IsComposableAttribute, "!targetFunction.IsComposableAttribute");
if (structuralTypeMappingsList.Count == 0)
{
this.ResultMappings = new OM.ReadOnlyCollection<FunctionImportStructuralTypeMappingKB>(
new FunctionImportStructuralTypeMappingKB[] {
new FunctionImportStructuralTypeMappingKB(new List<FunctionImportStructuralTypeMapping>(), itemCollection) });
this.noExplicitResultMappings = true;
}
else
{
Debug.Assert(functionImport.ReturnParameters.Count == structuralTypeMappingsList.Count);
this.ResultMappings = new OM.ReadOnlyCollection<FunctionImportStructuralTypeMappingKB>(
EntityUtil.CheckArgumentNull(structuralTypeMappingsList, "structuralTypeMappingsList")
.Select((structuralTypeMappings) => new FunctionImportStructuralTypeMappingKB(
EntityUtil.CheckArgumentNull(structuralTypeMappings, "structuralTypeMappings"),
itemCollection))
.ToArray());
this.noExplicitResultMappings = false;
}
}
private bool noExplicitResultMappings;
/// <summary>
/// Gets function import return type mapping knowledge bases.
/// </summary>
internal readonly OM.ReadOnlyCollection<FunctionImportStructuralTypeMappingKB> ResultMappings;
/// <summary>
/// If no return mappings were specified in the MSL return an empty return type mapping knowledge base.
/// Otherwise return the resultSetIndexth return type mapping knowledge base, or throw if resultSetIndex is out of range
/// </summary>
internal FunctionImportStructuralTypeMappingKB GetResultMapping(int resultSetIndex)
{
Debug.Assert(resultSetIndex >= 0, "resultSetIndex >= 0");
if (this.noExplicitResultMappings)
{
Debug.Assert(this.ResultMappings.Count == 1, "this.ResultMappings.Count == 1");
return this.ResultMappings[0];
}
else
{
if (ResultMappings.Count <= resultSetIndex)
{
EntityUtil.ThrowArgumentOutOfRangeException("resultSetIndex");
}
return this.ResultMappings[resultSetIndex];
}
}
/// <summary>
/// Gets the disctriminator columns resultSetIndexth result set, or an empty array if the index is not in range
/// </summary>
internal IList<string> GetDiscriminatorColumns(int resultSetIndex)
{
FunctionImportStructuralTypeMappingKB resultMapping = this.GetResultMapping(resultSetIndex);
return resultMapping.DiscriminatorColumns;
}
/// <summary>
/// Given discriminator values (ordinally aligned with DiscriminatorColumns), determines
/// the entity type to return. Throws a CommandExecutionException if the type is ambiguous.
/// </summary>
internal EntityType Discriminate(object[] discriminatorValues, int resultSetIndex)
{
FunctionImportStructuralTypeMappingKB resultMapping = this.GetResultMapping(resultSetIndex);
Debug.Assert (resultMapping != null);
// initialize matching types bit map
BitArray typeCandidates = new BitArray(resultMapping.MappedEntityTypes.Count, true);
foreach (var typeMapping in resultMapping.NormalizedEntityTypeMappings)
{
// check if this type mapping is matched
bool matches = true;
var columnConditions = typeMapping.ColumnConditions;
for (int i = 0; i < columnConditions.Count; i++)
{
if (null != columnConditions[i] && // this discriminator doesn't matter for the given condition
!columnConditions[i].ColumnValueMatchesCondition(discriminatorValues[i]))
{
matches = false;
break;
}
}
if (matches)
{
// if the type condition is met, narrow the set of type candidates
typeCandidates = typeCandidates.And(typeMapping.ImpliedEntityTypes);
}
else
{
// if the type condition fails, all implied types are eliminated
// (the type mapping fragment is a co-implication, so a type is no longer
// a candidate if any condition referring to it is false)
typeCandidates = typeCandidates.And(typeMapping.ComplementImpliedEntityTypes);
}
}
// find matching type condition
EntityType entityType = null;
for (int i = 0; i < typeCandidates.Length; i++)
{
if (typeCandidates[i])
{
if (null != entityType)
{
throw EntityUtil.CommandExecution(System.Data.Entity.Strings.ADP_InvalidDataReaderUnableToDetermineType);
}
entityType = resultMapping.MappedEntityTypes[i];
}
}
// if there is no match, raise an exception
if (null == entityType)
{
throw EntityUtil.CommandExecution(System.Data.Entity.Strings.ADP_InvalidDataReaderUnableToDetermineType);
}
return entityType;
}
/// <summary>
/// Determines the expected shape of store results. We expect a column for every property
/// of the mapped type (or types) and a column for every discriminator column. We make no
/// assumptions about the order of columns: the provider is expected to determine appropriate
/// types by looking at the names of the result columns, not the order of columns, which is
/// different from the typical handling of row types in the EF.
/// </summary>
/// <remarks>
/// Requires that the given function import mapping refers to a Collection(Entity) or Collection(ComplexType) CSDL
/// function.
/// </remarks>
/// <returns>Row type.</returns>
internal TypeUsage GetExpectedTargetResultType(MetadataWorkspace workspace, int resultSetIndex)
{
FunctionImportStructuralTypeMappingKB resultMapping = this.GetResultMapping(resultSetIndex);
// Collect all columns as name-type pairs.
Dictionary<string, TypeUsage> columns = new Dictionary<string, TypeUsage>();
// Figure out which entity types we expect to yield from the function.
IEnumerable<StructuralType> structuralTypes;
if (0 == resultMapping.NormalizedEntityTypeMappings.Count)
{
// No explicit type mappings; just use the type specified in the ReturnType attribute on the function.
StructuralType structuralType;
MetadataHelper.TryGetFunctionImportReturnType<StructuralType>(this.FunctionImport, resultSetIndex, out structuralType);
Debug.Assert(null != structuralType, "this method must be called only for entity/complextype reader function imports");
structuralTypes = new StructuralType[] { structuralType };
}
else
{
// Types are explicitly mapped.
structuralTypes = resultMapping.MappedEntityTypes.Cast<StructuralType>();
}
// Gather columns corresponding to all properties.
foreach (StructuralType structuralType in structuralTypes)
{
foreach (EdmProperty property in TypeHelpers.GetAllStructuralMembers(structuralType))
{
// NOTE: if a complex type is encountered, the column map generator will
// throw. For now, we just let them through.
// We expect to see each property multiple times, so we use indexer rather than
// .Add.
columns[property.Name] = property.TypeUsage;
}
}
// Gather discriminator columns.
foreach (string discriminatorColumn in this.GetDiscriminatorColumns(resultSetIndex))
{
if (!columns.ContainsKey(discriminatorColumn))
{
//
TypeUsage type = TypeUsage.CreateStringTypeUsage(workspace.GetModelPrimitiveType(PrimitiveTypeKind.String), true, false);
columns.Add(discriminatorColumn, type);
}
}
// Expected type is a collection of rows
RowType rowType = new RowType(columns.Select(c => new EdmProperty(c.Key, c.Value)));
TypeUsage result = TypeUsage.Create(new CollectionType(TypeUsage.Create(rowType)));
return result;
}
}
}

View File

@ -0,0 +1,33 @@
//---------------------------------------------------------------------
// <copyright file="Mapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Data.Metadata.Edm;
using System.Globalization;
namespace System.Data.Mapping
{
/// <summary>
/// Represents the base item class for all the mapping metadata
/// </summary>
internal abstract class Map : GlobalItem
{
protected Map()
: base(MetadataFlags.Readonly)
{
}
#region Properties
/// <summary>
/// Returns the Item that is being mapped either for ES or OE spaces.
/// The EDM type will be an EntityContainer type in ES mapping case.
/// In the OE mapping case it could be any type.
/// </summary>
internal abstract MetadataItem EdmItem { get; }
#endregion
}
}

View File

@ -0,0 +1,103 @@
//---------------------------------------------------------------------
// <copyright file="MappingItemCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Data.Mapping
{
using System;
using System.Data.Metadata.Edm;
/// <summary>
/// Class for representing a collection of mapping items in Edm space.
/// </summary>
[CLSCompliant(false)]
public abstract class MappingItemCollection : ItemCollection
{
/// <summary>
/// The default constructor for ItemCollection
/// </summary>
internal MappingItemCollection(DataSpace dataSpace) : base(dataSpace)
{
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="identity">identity of the type</param>
/// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
/// <param name="map"></param>
/// <returns>Returns false if no match found.</returns>
internal virtual bool TryGetMap(string identity, DataSpace typeSpace, out Map map)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="item"></param>
internal virtual Map GetMap(GlobalItem item)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="item"></param>
/// <param name="map"></param>
/// <returns>Returns false if no match found.</returns>
internal virtual bool TryGetMap(GlobalItem item, out Map map)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="identity">identity of the type</param>
/// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
/// <param name="ignoreCase">true for case-insensitive lookup</param>
/// <exception cref="ArgumentException"> Thrown if mapping space is not valid</exception>
internal virtual Map GetMap(string identity, DataSpace typeSpace, bool ignoreCase)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="identity">identity of the type</param>
/// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
/// <param name="ignoreCase">true for case-insensitive lookup</param>
/// <param name="map"></param>
/// <returns>Returns false if no match found.</returns>
internal virtual bool TryGetMap(string identity, DataSpace typeSpace, bool ignoreCase, out Map map)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
/// <summary>
/// Search for a Mapping metadata with the specified type key.
/// </summary>
/// <param name="identity">identity of the type</param>
/// <param name="typeSpace">The dataspace that the type for which map needs to be returned belongs to</param>
/// <exception cref="ArgumentException"> Thrown if mapping space is not valid</exception>
internal virtual Map GetMap(string identity, DataSpace typeSpace)
{
//will only be implemented by Mapping Item Collections
throw System.Data.Entity.Error.NotSupported();
}
}//---- ItemCollection
}//----

View File

@ -0,0 +1,213 @@
//---------------------------------------------------------------------
// <copyright file="MetadataMappingHasherVisitor.HashSourceBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Data.Common.Utils;
using System.Security.Cryptography;
using System.Globalization;
using System.IO;
namespace System.Data.Mapping
{
/// <summary>
/// This class keeps recomputing the hash and adding it to the front of the
/// builder when the length of the string gets too long
/// </summary>
internal class CompressingHashBuilder : StringHashBuilder
{
// this max comes from the value that Md5Hasher uses for a buffer size when it is reading
// from a stream
private const int HashCharacterCompressionThreshold = 0x1000 / 2; // num bytes / 2 to convert to typical unicode char size
private const int SpacesPerIndent = 4;
private int _indent = 0;
// we are starting the buffer at 1.5 times the number of bytes
// for the threshold
internal CompressingHashBuilder(HashAlgorithm hashAlgorithm)
: base(hashAlgorithm, (HashCharacterCompressionThreshold + (HashCharacterCompressionThreshold / 2)) * 2)
{
}
internal override void Append(string content)
{
base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' '));
base.Append(content);
CompressHash();
}
internal override void AppendLine(string content)
{
base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' '));
base.AppendLine(content);
CompressHash();
}
/// <summary>
/// add string like "typename Instance#1"
/// </summary>
/// <param name="objectIndex"></param>
internal void AppendObjectStartDump(object o, int objectIndex)
{
base.Append(string.Empty.PadLeft(SpacesPerIndent * _indent, ' '));
base.Append(o.GetType().ToString());
base.Append(" Instance#");
base.AppendLine(objectIndex.ToString(CultureInfo.InvariantCulture));
CompressHash();
this._indent++;
}
internal void AppendObjectEndDump()
{
Debug.Assert(this._indent > 0, "Indent and unindent should be paired");
this._indent--;
}
private void CompressHash()
{
if(base.CharCount >= HashCharacterCompressionThreshold)
{
string hash = ComputeHash();
Clear();
base.Append(hash);
}
}
}
/// <summary>
/// this class collects several strings together, and allows you to (
/// </summary>
internal class StringHashBuilder
{
private HashAlgorithm _hashAlgorithm;
private const string NewLine = "\n";
List<string> _strings = new List<string>();
int _totalLength;
byte[] _cachedBuffer;
internal StringHashBuilder(HashAlgorithm hashAlgorithm)
{
_hashAlgorithm = hashAlgorithm;
}
internal StringHashBuilder(HashAlgorithm hashAlgorithm, int startingBufferSize)
:this(hashAlgorithm)
{
Debug.Assert(startingBufferSize > 0, "should be a non zero positive integer");
_cachedBuffer = new byte[startingBufferSize];
}
internal int CharCount { get { return _totalLength; } }
internal virtual void Append(string s)
{
InternalAppend(s);
}
internal virtual void AppendLine(string s)
{
InternalAppend(s);
InternalAppend(NewLine);
}
private void InternalAppend(string s)
{
if (s.Length == 0)
return;
_strings.Add(s);
_totalLength += s.Length;
}
internal string ComputeHash()
{
int byteCount = GetByteCount();
if(_cachedBuffer == null)
{
// assume it is a one time use, and
// it will grow later if needed
_cachedBuffer = new byte[byteCount];
}
else if (_cachedBuffer.Length < byteCount)
{
// grow it by what is needed at a minimum, or 1.5 times bigger
// if that is bigger than what is needed this time. We
// make it 1.5 times bigger in hopes to reduce the number of allocations (consider the
// case where the next one it 1 bigger)
int bufferSize = Math.Max(_cachedBuffer.Length + (_cachedBuffer.Length / 2), byteCount);
_cachedBuffer = new byte[bufferSize];
}
int start = 0;
foreach (string s in _strings)
{
start += Encoding.Unicode.GetBytes(s, 0, s.Length, _cachedBuffer, start);
}
Debug.Assert(start == byteCount, "Did we use a different calculation for these?");
byte[] hash = _hashAlgorithm.ComputeHash(_cachedBuffer, 0, byteCount);
return ConvertHashToString(hash);
}
internal void Clear()
{
_strings.Clear();
_totalLength = 0;
}
public override string ToString()
{
StringBuilder builder = new StringBuilder();
_strings.ForEach(s => builder.Append(s));
return builder.ToString();
}
private int GetByteCount()
{
int count = 0;
foreach (string s in _strings)
{
count += Encoding.Unicode.GetByteCount(s);
}
return count;
}
private static string ConvertHashToString(byte[] hash)
{
StringBuilder stringData = new StringBuilder(hash.Length * 2);
// Loop through each byte of the data and format each one as a
// hexadecimal string
for (int i = 0; i < hash.Length; i++)
{
stringData.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
}
return stringData.ToString();
}
public static string ComputeHash(HashAlgorithm hashAlgorithm, string source)
{
StringHashBuilder builder = new StringHashBuilder(hashAlgorithm);
builder.Append(source);
return builder.ComputeHash();
}
}
}

View File

@ -0,0 +1,49 @@
//---------------------------------------------------------------------
// <copyright file="ObjectAssociationEndMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Mapping metadata for all OC member maps.
/// </summary>
internal class ObjectAssociationEndMapping: ObjectMemberMapping
{
#region Constructors
/// <summary>
/// Constrcut a new AssociationEnd member mapping metadata object
/// </summary>
/// <param name="edmAssociationEnd"></param>
/// <param name="clrAssociationEnd"></param>
internal ObjectAssociationEndMapping(AssociationEndMember edmAssociationEnd, AssociationEndMember clrAssociationEnd)
: base(edmAssociationEnd, clrAssociationEnd)
{
}
#endregion
#region Properties
/// <summary>
/// return the member mapping kind
/// </summary>
internal override MemberMappingKind MemberMappingKind
{
get
{
return MemberMappingKind.AssociationEndMapping;
}
}
#endregion
}
}

View File

@ -0,0 +1,55 @@
//---------------------------------------------------------------------
// <copyright file="ObjectComplexPropertyMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Xml;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Mapping metadata for complex member maps.
/// </summary>
internal class ObjectComplexPropertyMapping : ObjectPropertyMapping
{
#region Constructors
/// <summary>
/// Constrcut a new member mapping metadata object
/// </summary>
/// <param name="edmProperty"></param>
/// <param name="clrProperty"></param>
/// <param name="complexTypeMapping"></param>
internal ObjectComplexPropertyMapping(EdmProperty edmProperty, EdmProperty clrProperty, ObjectTypeMapping complexTypeMapping)
: base(edmProperty, clrProperty)
{
m_objectTypeMapping = complexTypeMapping;
}
#endregion
#region Fields
private readonly ObjectTypeMapping m_objectTypeMapping;
#endregion
#region Properties
/// <summary>
/// return the member mapping kind
/// </summary>
internal override MemberMappingKind MemberMappingKind
{
get
{
return MemberMappingKind.ComplexPropertyMapping;
}
}
#endregion
}
}

View File

@ -0,0 +1,86 @@
//---------------------------------------------------------------------
// <copyright file="ObjectMemberMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Mapping metadata for all OC member maps.
/// </summary>
internal abstract class ObjectMemberMapping
{
#region Constructors
/// <summary>
/// Constrcut a new member mapping metadata object
/// </summary>
/// <param name="edmMember"></param>
/// <param name="clrMember"></param>
protected ObjectMemberMapping(EdmMember edmMember, EdmMember clrMember)
{
System.Diagnostics.Debug.Assert(edmMember.BuiltInTypeKind == clrMember.BuiltInTypeKind, "BuiltInTypeKind must be the same");
this.m_edmMember = edmMember;
this.m_clrMember = clrMember;
}
#endregion
#region Fields
#region Internal
EdmMember m_edmMember; //EdmMember metadata representing the Cdm member for which the mapping is specified
EdmMember m_clrMember; //EdmMember metadata representing the Clr member for which the mapping is specified
#endregion
#endregion
#region Properties
/// <summary>
/// The PropertyMetadata object that represents the Cdm member for which mapping is being specified
/// </summary>
internal EdmMember EdmMember
{
get
{
return this.m_edmMember;
}
}
/// <summary>
/// The PropertyMetadata object that represents the Clr member for which mapping is being specified
/// </summary>
internal EdmMember ClrMember
{
get
{
return this.m_clrMember;
}
}
/// <summary>
/// Returns the member mapping kind
/// </summary>
internal abstract MemberMappingKind MemberMappingKind { get; }
#endregion
}
/// <summary>
/// Represents the various kind of member mapping
/// </summary>
internal enum MemberMappingKind
{
ScalarPropertyMapping = 0,
NavigationPropertyMapping = 1,
AssociationEndMapping =2,
ComplexPropertyMapping = 3,
}
}

View File

@ -0,0 +1,28 @@
//---------------------------------------------------------------------
// <copyright file="ObjectMslConstructs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner leil
// @backupOwner anpete
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace System.Data.Mapping
{
/// <summary>
/// Defines all the string constrcuts defined in OC MSL specification
/// </summary>
internal static class ObjectMslConstructs {
#region Fields
internal const string MappingElement = "Mapping";
internal const string AliasElement = "Alias";
internal const string AliasKeyAttribute = "Key";
internal const string AliasValueAttribute = "Value";
internal const char IdentitySeperator = ':';
#endregion
}
}

View File

@ -0,0 +1,48 @@
//---------------------------------------------------------------------
// <copyright file="ObjectNsavigationPropertyMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Mapping metadata for all OC member maps.
/// </summary>
internal class ObjectNavigationPropertyMapping: ObjectMemberMapping
{
#region Constructors
/// <summary>
/// Constrcut a new member mapping metadata object
/// </summary>
/// <param name="edmNavigationProperty"></param>
/// <param name="clrNavigationProperty"></param>
internal ObjectNavigationPropertyMapping(NavigationProperty edmNavigationProperty, NavigationProperty clrNavigationProperty) :
base(edmNavigationProperty, clrNavigationProperty)
{
}
#endregion
#region Properties
/// <summary>
/// return the member mapping kind
/// </summary>
internal override MemberMappingKind MemberMappingKind
{
get
{
return MemberMappingKind.NavigationPropertyMapping;
}
}
#endregion
}
}

View File

@ -0,0 +1,59 @@
//---------------------------------------------------------------------
// <copyright file="ObjectPropertyMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Mapping metadata for all OC member maps.
/// </summary>
internal class ObjectPropertyMapping: ObjectMemberMapping
{
#region Constructors
/// <summary>
/// Constrcut a new member mapping metadata object
/// </summary>
/// <param name="edmProperty"></param>
/// <param name="clrProperty"></param>
internal ObjectPropertyMapping(EdmProperty edmProperty, EdmProperty clrProperty) :
base(edmProperty, clrProperty)
{
}
#endregion
#region Properties
/// <summary>
/// The PropertyMetadata object that represents the Clr member for which mapping is being specified
/// </summary>
internal EdmProperty ClrProperty
{
get
{
return (EdmProperty)this.ClrMember;
}
}
/// <summary>
/// return the member mapping kind
/// </summary>
internal override MemberMappingKind MemberMappingKind
{
get
{
return MemberMappingKind.ScalarPropertyMapping;
}
}
#endregion
}
}

View File

@ -0,0 +1,197 @@
//---------------------------------------------------------------------
// <copyright file="ObjectTypeMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Data.Mapping {
using System;
using System.Collections.Generic;
using System.Data.Metadata.Edm;
using System.Diagnostics;
/// <summary>
/// Represents the metadata for OCObjectMapping.
/// </summary>
internal class ObjectTypeMapping : Map {
#region Constructors
/// <summary>
/// Construct a new ObjectTypeMapping object
/// </summary>
/// <param name="clrType"></param>
/// <param name="cdmType"></param>
internal ObjectTypeMapping(EdmType clrType, EdmType cdmType) {
Debug.Assert(clrType.BuiltInTypeKind == cdmType.BuiltInTypeKind, "BuiltInTypeKind must be the same for both types");
this.m_clrType = clrType;
this.m_cdmType = cdmType;
identity = clrType.Identity + ObjectMslConstructs.IdentitySeperator + cdmType.Identity;
if (Helper.IsStructuralType(cdmType))
{
m_memberMapping = new Dictionary<string, ObjectMemberMapping>(((StructuralType)cdmType).Members.Count);
}
else
{
m_memberMapping = EmptyMemberMapping;
}
}
#endregion
#region Fields
#region Internal
private readonly EdmType m_clrType; //type on the Clr side that is being mapped
private readonly EdmType m_cdmType; //type on the Cdm side that is being mapped
private readonly string identity;
private readonly Dictionary<string, ObjectMemberMapping> m_memberMapping; //Indexes into the member mappings collection based on clr member name
private static readonly Dictionary<string, ObjectMemberMapping> EmptyMemberMapping
= new Dictionary<string, ObjectMemberMapping>(0);
#endregion
#endregion
#region Properties
/// <summary>
/// Gets the type kind for this item
/// </summary>
public override BuiltInTypeKind BuiltInTypeKind {
get { return BuiltInTypeKind.MetadataItem; }
}
/// <summary>
/// The reference to the Clr type in Metadata
/// that participates in this mapping instance
/// </summary>
internal EdmType ClrType {
get {
return this.m_clrType;
}
}
/// <summary>
/// The reference to the Cdm type in Metadata
/// that participates in this mapping instance
/// </summary>
internal override MetadataItem EdmItem {
get {
return this.EdmType;
}
}
/// <summary>
/// The reference to the Cdm type in Metadata
/// that participates in this mapping instance
/// </summary>
internal EdmType EdmType {
get {
return this.m_cdmType;
}
}
/// <summary>
/// Returns the Identity of ObjectTypeMapping.
/// The identity for an Object Type Map is the concatenation of
/// CLR Type Idntity + ':' + CDM Type Identity
/// </summary>
internal override string Identity {
get {
return identity;
}
}
#endregion
#region Methods
/// <summary>
/// get a MemberMap for the member name specified
/// </summary>
/// <param name="cdmPropertyName">the name of the CDM member for which map needs to be retrieved</param>
internal ObjectPropertyMapping GetPropertyMap(String propertyName)
{
ObjectMemberMapping memberMapping = GetMemberMap(propertyName, false /*ignoreCase*/);
if (memberMapping != null &&
memberMapping.MemberMappingKind == MemberMappingKind.ScalarPropertyMapping ||
memberMapping.MemberMappingKind == MemberMappingKind.ComplexPropertyMapping)
{
return (ObjectPropertyMapping)memberMapping;
}
return null;
}
/// <summary>
/// Add a member mapping as a child of this object mapping
/// </summary>
/// <param name="property">child property mapping to be added</param>
internal void AddMemberMap(ObjectMemberMapping memberMapping) {
Debug.Assert(memberMapping.ClrMember.Name == memberMapping.EdmMember.Name,
"Both clrmember and edmMember name must be the same");
//Check to see if either the Clr member or the Cdm member specified in this
//type has already been mapped.
Debug.Assert(!m_memberMapping.ContainsKey(memberMapping.EdmMember.Name));
Debug.Assert(!Type.ReferenceEquals(m_memberMapping, EmptyMemberMapping),
"Make sure you don't add anything to the static emtpy member mapping");
m_memberMapping.Add(memberMapping.EdmMember.Name, memberMapping);
}
/// <summary>
/// Returns the member map for the given clr member
/// </summary>
/// <param name="clrPropertyName"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
internal ObjectMemberMapping GetMemberMapForClrMember(string clrMemberName, bool ignoreCase)
{
return GetMemberMap(clrMemberName, ignoreCase);
}
/// <summary>
/// returns the member mapping for the given member
/// </summary>
/// <param name="propertyName"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
private ObjectMemberMapping GetMemberMap(string propertyName, bool ignoreCase)
{
EntityUtil.CheckStringArgument(propertyName, "propertyName");
ObjectMemberMapping memberMapping = null;
if (!ignoreCase)
{
//First get the index of the member map from the clr indexs
m_memberMapping.TryGetValue(propertyName, out memberMapping);
}
else
{
foreach (KeyValuePair<string, ObjectMemberMapping> keyValuePair in m_memberMapping)
{
if (keyValuePair.Key.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
{
if (memberMapping != null)
{
throw new MappingException(System.Data.Entity.Strings.Mapping_Duplicate_PropertyMap_CaseInsensitive(
propertyName));
}
memberMapping = keyValuePair.Value;
}
}
}
return memberMapping;
}
/// <summary>
/// Overriding System.Object.ToString to provide better String representation
/// for this type.
/// </summary>
public override string ToString()
{
return this.Identity;
}
#endregion
}
}

View File

@ -0,0 +1,105 @@
//---------------------------------------------------------------------
// <copyright file="StorageAssociationSetMapping.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping {
/// <summary>
/// Represents the Mapping metadata for an AssociationSet in CS space.
/// </summary>
/// <example>
/// For Example if conceptually you could represent the CS MSL file as following
/// --Mapping
/// --EntityContainerMapping ( CNorthwind-->SNorthwind )
/// --EntitySetMapping
/// --EntityTypeMapping
/// --MappingFragment
/// --EntityTypeMapping
/// --MappingFragment
/// --AssociationSetMapping
/// --AssociationTypeMapping
/// --MappingFragment
/// This class represents the metadata for the AssociationSetMapping elements in the
/// above example. And it is possible to access the AssociationTypeMap underneath it.
/// There will be only one TypeMap under AssociationSetMap.
/// </example>
internal class StorageAssociationSetMapping : StorageSetMapping {
#region Constructors
/// <summary>
/// Construct a new AssociationSetMapping object
/// </summary>
/// <param name="extent">Represents the Association Set Metadata object. Will
/// change this to Extent instead of MemberMetadata.</param>
/// <param name="entityContainerMapping">The entityContainerMapping mapping that contains this Set mapping</param>
internal StorageAssociationSetMapping(AssociationSet extent, StorageEntityContainerMapping entityContainerMapping)
: base(extent, entityContainerMapping) {
}
#endregion
#region Fields
private StorageAssociationSetModificationFunctionMapping m_modificationFunctionMapping;
#endregion
#region Properties
/// <summary>
/// Gets or sets function mapping information for this association set. May be null.
/// </summary>
internal StorageAssociationSetModificationFunctionMapping ModificationFunctionMapping {
get { return m_modificationFunctionMapping; }
set { m_modificationFunctionMapping = value; }
}
internal EntitySetBase StoreEntitySet
{
get
{
if ((this.TypeMappings.Count != 0) && (this.TypeMappings.First().MappingFragments.Count != 0))
{
return this.TypeMappings.First().MappingFragments.First().TableSet;
}
return null;
}
}
#endregion
#region Methods
/// <summary>
/// This method is primarily for debugging purposes.
/// Will be removed shortly.
/// </summary>
/// <param name="index"></param>
internal override void Print(int index) {
StorageEntityContainerMapping.GetPrettyPrintString(ref index);
StringBuilder sb = new StringBuilder();
sb.Append("AssociationSetMapping");
sb.Append(" ");
sb.Append("Name:");
sb.Append(this.Set.Name);
if (this.QueryView != null)
{
sb.Append(" ");
sb.Append("Query View:");
sb.Append(this.QueryView);
}
Console.WriteLine(sb.ToString());
foreach (StorageTypeMapping typeMapping in TypeMappings) {
typeMapping.Print(index + 5);
}
if(m_modificationFunctionMapping != null)
{
m_modificationFunctionMapping.Print(index + 5);
}
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More