You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
}//----
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
Reference in New Issue
Block a user