Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Mapping / FunctionImportMapping.cs / 1305376 / FunctionImportMapping.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Xml; using System.Data.Common.Utils; using System.Data.Entity; using OM = System.Collections.ObjectModel; using System.Globalization; using System.Diagnostics; using System.Collections; using System.Data.Common.Utils.Boolean; using System.Xml.XPath; using System.Collections.ObjectModel; namespace System.Data.Mapping { ////// Represents a mapping from a model FunctionImport to a store /// non-composable Function. /// internal sealed class FunctionImportMapping { internal FunctionImportMapping(EdmFunction targetFunction, EdmFunction functionImport, IEnumerablestructuralTypeMappings, ItemCollection itemCollection) { this.TargetFunction = EntityUtil.CheckArgumentNull(targetFunction, "targetFunction"); this.FunctionImport = EntityUtil.CheckArgumentNull(functionImport, "functionImport"); EntityUtil.CheckArgumentNull(itemCollection, "itemCollection"); EntityUtil.CheckArgumentNull(structuralTypeMappings, "structuralTypeMappings"); Dictionary > isOfTypeEntityTypeColumnsRenameMapping = new Dictionary >(); Dictionary > entityTypeColumnsRenameMapping = new Dictionary >(); // normalize the type mappings var normalizedEntityTypeMappings = new List (); // if no specific type mapping if(structuralTypeMappings.Count() == 0) { // initialize this.ReturnTypeColumnsRenameMapping = new Dictionary (); this.NormalizedEntityTypeMappings = new System.Collections.ObjectModel.ReadOnlyCollection ( normalizedEntityTypeMappings); this.DiscriminatorColumns = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); this.MappedEntityTypes = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); return; } IEnumerable entityTypeMappings = structuralTypeMappings.OfType (); // FunctionImportEntityTypeMapping if (null != entityTypeMappings && null != entityTypeMappings.FirstOrDefault ()) { // collect all mapped entity types this.MappedEntityTypes = entityTypeMappings .SelectMany(mapping => mapping.GetMappedEntityTypes(itemCollection)) .Distinct() .ToList() .AsReadOnly(); // collect all discriminator columns this.DiscriminatorColumns = entityTypeMappings .SelectMany(mapping => mapping.GetDiscriminatorColumns()) .Distinct() .ToList() .AsReadOnly(); this.EntityTypeLineInfos = new KeyToListMap (EqualityComparer .Default); this.IsTypeOfLineInfos = new KeyToListMap (EqualityComparer .Default); foreach (var entityTypeMapping in entityTypeMappings) { // remember LineInfos for error reporting foreach (var entityType in entityTypeMapping.EntityTypes) { this.EntityTypeLineInfos.Add(entityType, entityTypeMapping.LineInfo); } foreach (var isTypeOf in entityTypeMapping.IsOfTypeEntityTypes) { this.IsTypeOfLineInfos.Add(isTypeOf, entityTypeMapping.LineInfo); } // create map from column name to condition var columnMap = entityTypeMapping.Conditions.ToDictionary( condition => condition.ColumnName, condition => condition); // align conditions with discriminator columns var columnMappings = new List (this.DiscriminatorColumns.Count); for (int i = 0; i < this.DiscriminatorColumns.Count; i++) { string discriminatorColumn = this.DiscriminatorColumns[i]; FunctionImportEntityTypeMappingCondition mappingCondition; if (columnMap.TryGetValue(discriminatorColumn, out mappingCondition)) { columnMappings.Add(mappingCondition); } else { // null indicates the value for this discriminator doesn't matter columnMappings.Add(null); } } // create bit map for implied entity types bool[] impliedEntityTypesBitMap = new bool[this.MappedEntityTypes.Count]; var impliedEntityTypesSet = new Set (entityTypeMapping.GetMappedEntityTypes(itemCollection)); for (int i = 0; i < this.MappedEntityTypes.Count; i++) { impliedEntityTypesBitMap[i] = impliedEntityTypesSet.Contains(this.MappedEntityTypes[i]); } // construct normalized mapping normalizedEntityTypeMappings.Add(new FunctionImportNormalizedEntityTypeMapping(this, columnMappings, new BitArray(impliedEntityTypesBitMap))); // construct the rename mappings by adding isTypeOf types and specific entity types to the corresponding lists foreach (var isOfType in entityTypeMapping.IsOfTypeEntityTypes) { if (!isOfTypeEntityTypeColumnsRenameMapping.Keys.Contains(isOfType)) { isOfTypeEntityTypeColumnsRenameMapping.Add(isOfType, entityTypeMapping.ColumnsRenameList); } else { foreach (var rename in entityTypeMapping.ColumnsRenameList) { isOfTypeEntityTypeColumnsRenameMapping[isOfType].Add(rename); } } } foreach (var entityType in entityTypeMapping.EntityTypes) { if (!entityTypeColumnsRenameMapping.Keys.Contains(entityType)) { entityTypeColumnsRenameMapping.Add(entityType, entityTypeMapping.ColumnsRenameList); } else { foreach (var rename in entityTypeMapping.ColumnsRenameList) { entityTypeColumnsRenameMapping[entityType].Add(rename); } } } } this.ReturnTypeColumnsRenameMapping = new FunctionImportReturnTypeEntityTypeColumnsRenameBuilder( isOfTypeEntityTypeColumnsRenameMapping, entityTypeColumnsRenameMapping).ColumnRenameMapping; this.NormalizedEntityTypeMappings = new OM.ReadOnlyCollection ( normalizedEntityTypeMappings); } else { // FunctionImportComplexTypeMapping Debug.Assert(structuralTypeMappings.First() is FunctionImportComplexTypeMapping, "only two types can have renames, complexType and entityType"); IEnumerable complexTypeMappings = structuralTypeMappings.Cast (); Debug.Assert(complexTypeMappings.Count() == 1, "how come there are more than 1, complex type cannot derive from other complex type"); this.ReturnTypeColumnsRenameMapping = new Dictionary (); foreach (var rename in complexTypeMappings.First().ColumnsRenameList) { FunctionImportReturnTypeStructuralTypeColumnRenameMapping columnRenameMapping = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(rename.CMember); columnRenameMapping.AddRename(new FunctionImportReturnTypeStructuralTypeColumn( rename.SColumn, complexTypeMappings.First().ReturnType, false)); this.ReturnTypeColumnsRenameMapping.Add(rename.CMember, columnRenameMapping); } // initialize the extra data this.NormalizedEntityTypeMappings = new System.Collections.ObjectModel.ReadOnlyCollection ( normalizedEntityTypeMappings); this.DiscriminatorColumns = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); this.MappedEntityTypes = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); } } /// /// Gets store function (or target of the mapping) /// internal readonly EdmFunction TargetFunction; ////// Gets model function (or source of the mapping) /// internal readonly EdmFunction FunctionImport; ////// Gets all types in scope for this mapping. /// internal readonly OM.ReadOnlyCollectionMappedEntityTypes; /// /// Gets a list of all discriminator columns used in this mapping. /// internal readonly OM.ReadOnlyCollectionDiscriminatorColumns; /// /// Gets normalized representation of all EntityTypeMapping fragments for this /// function import mapping. /// internal readonly OM.ReadOnlyCollectionNormalizedEntityTypeMappings; /// /// Gets line infos for entity type mappings. /// internal readonly KeyToListMapEntityTypeLineInfos; /// /// Gets line infos for IsTypeOf mappings for entity types. /// internal readonly KeyToListMapIsTypeOfLineInfos; /// /// Get the columns rename mapping for return type, the first string is the member name /// the second one is column names for different types that mentioned in the mapping. /// internal readonly DictionaryReturnTypeColumnsRenameMapping; /// /// Given discriminator values (ordinally aligned with DiscriminatorColumns), determines /// the entity type to return. Throws a CommandExecutionException if the type is ambiguous. /// internal EntityType Discriminate(object[] discriminatorValues) { // initialize matching types bit map BitArray typeCandidates = new BitArray(this.MappedEntityTypes.Count, true); foreach (var typeMapping in this.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 = this.MappedEntityTypes[i]; } } // if there is no match, raise an exception if (null == entityType) { throw EntityUtil.CommandExecution(System.Data.Entity.Strings.ADP_InvalidDataReaderUnableToDetermineType); } return entityType; } ////// Determines which explicitly mapped types in the function import mapping cannot be generated. /// For IsTypeOf declarations, reports if no type in hierarchy can be produced. /// /// Works by: /// /// - Converting type mapping conditions into vertices /// - Checking that some assignment satisfies /// internal void GetUnreachableTypes(EdmItemCollection itemCollection, out KeyToListMapunreachableEntityTypes, out KeyToListMap unreachableIsTypeOfs) { // Contains, for each DiscriminatorColumn, a domain variable where the domain values are // integers representing the ordinal within discriminatorDomains DomainVariable [] variables = ConstructDomainVariables(); // Convert type mapping conditions to decision diagram vertices var converter = new DomainConstraintConversionContext (); Vertex[] mappingConditions = ConvertMappingConditionsToVertices(converter, variables); // Find reachable types Set reachableTypes = FindReachableTypes(converter, mappingConditions); CollectUnreachableTypes(itemCollection, reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs); } /// /// 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. /// ////// Requires that the given function import mapping refers to a Collection(Entity) or Collection(ComplexType) CSDL /// function. /// ///Row type. internal TypeUsage GetExpectedTargetResultType(MetadataWorkspace workspace) { // Collect all columns as name-type pairs. Dictionarycolumns = new Dictionary (); // Figure out which entity types we expect to yield from the function. IEnumerable structuralTypes; if (0 == this.NormalizedEntityTypeMappings.Count) { // No explicit type mappings; just use the type specified in the ReturnType attribute on the function. StructuralType structuralType; MetadataHelper.TryGetFunctionImportReturnType (this.FunctionImport, 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 = this.MappedEntityTypes.Cast (); } // 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.DiscriminatorColumns) { 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; } /// /// Determines which types are produced by this mapping /// private SetFindReachableTypes(DomainConstraintConversionContext converter, Vertex[] mappingConditions) { Set reachableTypes = new Set (); // for each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true // and its negative conditions evaluate to false Vertex[] candidateFunctions = new Vertex[this.MappedEntityTypes.Count]; for (int i = 0; i < candidateFunctions.Length; i++) { // seed the candidate function conjunction with 'true' Vertex candidateFunction = Vertex.One; for (int j = 0; j < this.NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = this.NormalizedEntityTypeMappings[j]; // determine if this mapping is a positive or negative case for the current type if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } else { candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j])); } } candidateFunctions[i] = candidateFunction; } // for each type, make sure there is some assignment that resolves to only that type for (int i = 0; i < candidateFunctions.Length; i++) { // create a function that evaluates to true iff. the current candidate function is true // and every other candidate function is false Vertex isExactlyThisTypeCondition = converter.Solver.And( candidateFunctions.Select((typeCondition, ordinal) => ordinal == i ? typeCondition : converter.Solver.Not(typeCondition))); // if the above conjunction is satisfiable, it means some row configuration exists // producing the type if (!isExactlyThisTypeCondition.IsZero()) { reachableTypes.Add(this.MappedEntityTypes[i]); } } return reachableTypes; } private void CollectUnreachableTypes(EdmItemCollection itemCollection, Set reachableTypes, out KeyToListMap entityTypes, out KeyToListMap isTypeOfEntityTypes) { // Collect line infos for types in violation entityTypes = new KeyToListMap (EqualityComparer .Default); isTypeOfEntityTypes = new KeyToListMap (EqualityComparer .Default); if (reachableTypes.Count == this.MappedEntityTypes.Count) { // All types are reachable; nothing to check return; } // Find IsTypeOf mappings where no type in hierarchy can generate a row foreach (var isTypeOf in this.IsTypeOfLineInfos.Keys) { if (!MetadataHelper.GetTypeAndSubtypesOf(isTypeOf, itemCollection, false) .Cast () .Intersect(reachableTypes) .Any()) { // no type in the hierarchy is reachable... isTypeOfEntityTypes.AddRange(isTypeOf, this.IsTypeOfLineInfos.EnumerateValues(isTypeOf)); } } // Find explicit types not generating a value foreach (var entityType in this.EntityTypeLineInfos.Keys) { if (!reachableTypes.Contains(entityType)) { entityTypes.AddRange(entityType, this.EntityTypeLineInfos.EnumerateValues(entityType)); } } } private DomainVariable [] ConstructDomainVariables() { // determine domain for each discriminator column, including "other" and "null" placeholders var discriminatorDomains = new Set [this.DiscriminatorColumns.Count]; for (int i = 0; i < discriminatorDomains.Length; i++) { discriminatorDomains[i] = new Set (); discriminatorDomains[i].Add(ValueCondition.IsOther); discriminatorDomains[i].Add(ValueCondition.IsNull); } // collect all domain values foreach (var typeMapping in this.NormalizedEntityTypeMappings) { for (int i = 0; i < this.DiscriminatorColumns.Count; i++) { var discriminatorValue = typeMapping.ColumnConditions[i]; if (null != discriminatorValue && !discriminatorValue.ConditionValue.IsNotNullCondition) // NotNull is a special range (everything but IsNull) { discriminatorDomains[i].Add(discriminatorValue.ConditionValue); } } } var discriminatorVariables = new DomainVariable [discriminatorDomains.Length]; for (int i = 0; i < discriminatorVariables.Length; i++) { // domain variable is identified by the column name and takes all collected domain values discriminatorVariables[i] = new DomainVariable (this.DiscriminatorColumns[i], discriminatorDomains[i].MakeReadOnly()); } return discriminatorVariables; } private Vertex[] ConvertMappingConditionsToVertices(ConversionContext > converter, DomainVariable [] variables) { Vertex[] conditions = new Vertex[this.NormalizedEntityTypeMappings.Count]; for (int i = 0; i < conditions.Length; i++) { var typeMapping = this.NormalizedEntityTypeMappings[i]; // create conjunction representing the condition Vertex condition = Vertex.One; for (int j = 0; j < this.DiscriminatorColumns.Count; j++) { var columnCondition = typeMapping.ColumnConditions[j]; if (null != columnCondition) { var conditionValue = columnCondition.ConditionValue; if (conditionValue.IsNotNullCondition) { // the 'not null' condition is not actually part of the domain (since it // covers other elements), so create a Not(value in {null}) condition var isNull = new TermExpr >( new DomainConstraint (variables[j], ValueCondition.IsNull)); Vertex isNullVertex = converter.TranslateTermToVertex(isNull); condition = converter.Solver.And(condition, converter.Solver.Not(isNullVertex)); } else { var hasValue = new TermExpr >( new DomainConstraint (variables[j], conditionValue)); condition = converter.Solver.And(condition, converter.TranslateTermToVertex(hasValue)); } } } conditions[i] = condition; } return conditions; } } internal sealed class FunctionImportNormalizedEntityTypeMapping { internal FunctionImportNormalizedEntityTypeMapping(FunctionImportMapping parent, List columnConditions, BitArray impliedEntityTypes) { // validate arguments EntityUtil.CheckArgumentNull(parent, "parent"); EntityUtil.CheckArgumentNull(columnConditions, "discriminatorValues"); EntityUtil.CheckArgumentNull(impliedEntityTypes, "impliedEntityTypes"); Debug.Assert(columnConditions.Count == parent.DiscriminatorColumns.Count, "discriminator values must be ordinally aligned with discriminator columns"); Debug.Assert(impliedEntityTypes.Count == parent.MappedEntityTypes.Count, "implied entity types must be ordinally aligned with mapped entity types"); this.ColumnConditions = new OM.ReadOnlyCollection (columnConditions.ToList()); this.ImpliedEntityTypes = impliedEntityTypes; this.ComplementImpliedEntityTypes = (new BitArray(this.ImpliedEntityTypes)).Not(); } /// /// Gets discriminator values aligned with DiscriminatorColumns of the parent FunctionImportMapping. /// A null ValueCondition indicates 'anything goes'. /// internal readonly OM.ReadOnlyCollectionColumnConditions; /// /// Gets bit array with 'true' indicating the corresponding MappedEntityType of the parent /// FunctionImportMapping is implied by this fragment. /// internal readonly BitArray ImpliedEntityTypes; ////// Gets the complement of the ImpliedEntityTypes BitArray. /// internal readonly BitArray ComplementImpliedEntityTypes; public override string ToString() { return String.Format(CultureInfo.InvariantCulture, "Values={0}, Types={1}", StringUtil.ToCommaSeparatedString(this.ColumnConditions), StringUtil.ToCommaSeparatedString(this.ImpliedEntityTypes)); } } internal abstract class FunctionImportEntityTypeMappingCondition { protected FunctionImportEntityTypeMappingCondition(string columnName) { this.ColumnName = EntityUtil.CheckArgumentNull(columnName, "columnName"); } internal abstract ValueCondition ConditionValue { get; } internal readonly string ColumnName; internal abstract bool ColumnValueMatchesCondition(object columnValue); public override string ToString() { return this.ConditionValue.ToString(); } } internal sealed class FunctionImportEntityTypeMappingConditionValue : FunctionImportEntityTypeMappingCondition { internal FunctionImportEntityTypeMappingConditionValue(string columnName, XPathNavigator columnValue) : base(columnName) { this._xPathValue = EntityUtil.CheckArgumentNull(columnValue, "columnValue"); this._convertedValues = new Memoizer(this.GetConditionValue, null); } private readonly XPathNavigator _xPathValue; private readonly Memoizer _convertedValues; internal override ValueCondition ConditionValue { get { return new ValueCondition(_xPathValue.Value); } } internal override bool ColumnValueMatchesCondition(object columnValue) { if (null == columnValue || Convert.IsDBNull(columnValue)) { // only FunctionImportEntityTypeMappingConditionIsNull can match a null // column value return false; } Type columnValueType = columnValue.GetType(); // check if we've interpreted this column type yet object conditionValue = _convertedValues.Evaluate(columnValueType); return ByValueEqualityComparer.Default.Equals(columnValue, conditionValue); } private object GetConditionValue(Type columnValueType) { object conditionValue; // check that the type is supported PrimitiveType primitiveType; if (!ClrProviderManifest.Instance.TryGetPrimitiveType(columnValueType, out primitiveType) || !StorageMappingItemLoader.IsTypeSupportedForCondition(primitiveType.PrimitiveTypeKind)) { throw EntityUtil.CommandExecution(Strings.Mapping_FunctionImport_UnsupportedType( this.ColumnName, columnValueType.FullName)); } try { conditionValue = _xPathValue.ValueAs(columnValueType); } catch (FormatException) { throw EntityUtil.CommandExecution(Strings.Mapping_FunctionImport_ConditionValueTypeMismatch( StorageMslConstructs.FunctionImportMappingElement, this.ColumnName, columnValueType.FullName)); } return conditionValue; } } internal sealed class FunctionImportEntityTypeMappingConditionIsNull : FunctionImportEntityTypeMappingCondition { internal FunctionImportEntityTypeMappingConditionIsNull(string columnName, bool isNull) : base(columnName) { this.IsNull = isNull; } internal readonly bool IsNull; internal override ValueCondition ConditionValue { get { return IsNull ? ValueCondition.IsNull : ValueCondition.IsNotNull; } } internal override bool ColumnValueMatchesCondition(object columnValue) { bool valueIsNull = null == columnValue || Convert.IsDBNull(columnValue); return valueIsNull == this.IsNull; } } /// /// Represents a simple value condition of the form (value IS NULL), (value IS NOT NULL) /// or (value EQ X). Supports IEquatable(Of ValueCondition) so that equivalent conditions /// can be identified. /// internal class ValueCondition : IEquatable{ internal readonly string Description; internal readonly bool IsSentinel; internal const string IsNullDescription = "NULL"; internal const string IsNotNullDescription = "NOT NULL"; internal const string IsOtherDescription = "OTHER"; internal readonly static ValueCondition IsNull = new ValueCondition(IsNullDescription, true); internal readonly static ValueCondition IsNotNull = new ValueCondition(IsNotNullDescription, true); internal readonly static ValueCondition IsOther = new ValueCondition(IsOtherDescription, true); private ValueCondition(string description, bool isSentinel) { Description = description; IsSentinel = isSentinel; } internal ValueCondition(string description) : this(description, false) { } internal bool IsNotNullCondition { get { return object.ReferenceEquals(this, IsNotNull); } } public bool Equals(ValueCondition other) { return other.IsSentinel == this.IsSentinel && other.Description == this.Description; } public override int GetHashCode() { return Description.GetHashCode(); } public override string ToString() { return this.Description; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Xml; using System.Data.Common.Utils; using System.Data.Entity; using OM = System.Collections.ObjectModel; using System.Globalization; using System.Diagnostics; using System.Collections; using System.Data.Common.Utils.Boolean; using System.Xml.XPath; using System.Collections.ObjectModel; namespace System.Data.Mapping { ////// Represents a mapping from a model FunctionImport to a store /// non-composable Function. /// internal sealed class FunctionImportMapping { internal FunctionImportMapping(EdmFunction targetFunction, EdmFunction functionImport, IEnumerablestructuralTypeMappings, ItemCollection itemCollection) { this.TargetFunction = EntityUtil.CheckArgumentNull(targetFunction, "targetFunction"); this.FunctionImport = EntityUtil.CheckArgumentNull(functionImport, "functionImport"); EntityUtil.CheckArgumentNull(itemCollection, "itemCollection"); EntityUtil.CheckArgumentNull(structuralTypeMappings, "structuralTypeMappings"); Dictionary > isOfTypeEntityTypeColumnsRenameMapping = new Dictionary >(); Dictionary > entityTypeColumnsRenameMapping = new Dictionary >(); // normalize the type mappings var normalizedEntityTypeMappings = new List (); // if no specific type mapping if(structuralTypeMappings.Count() == 0) { // initialize this.ReturnTypeColumnsRenameMapping = new Dictionary (); this.NormalizedEntityTypeMappings = new System.Collections.ObjectModel.ReadOnlyCollection ( normalizedEntityTypeMappings); this.DiscriminatorColumns = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); this.MappedEntityTypes = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); return; } IEnumerable entityTypeMappings = structuralTypeMappings.OfType (); // FunctionImportEntityTypeMapping if (null != entityTypeMappings && null != entityTypeMappings.FirstOrDefault ()) { // collect all mapped entity types this.MappedEntityTypes = entityTypeMappings .SelectMany(mapping => mapping.GetMappedEntityTypes(itemCollection)) .Distinct() .ToList() .AsReadOnly(); // collect all discriminator columns this.DiscriminatorColumns = entityTypeMappings .SelectMany(mapping => mapping.GetDiscriminatorColumns()) .Distinct() .ToList() .AsReadOnly(); this.EntityTypeLineInfos = new KeyToListMap (EqualityComparer .Default); this.IsTypeOfLineInfos = new KeyToListMap (EqualityComparer .Default); foreach (var entityTypeMapping in entityTypeMappings) { // remember LineInfos for error reporting foreach (var entityType in entityTypeMapping.EntityTypes) { this.EntityTypeLineInfos.Add(entityType, entityTypeMapping.LineInfo); } foreach (var isTypeOf in entityTypeMapping.IsOfTypeEntityTypes) { this.IsTypeOfLineInfos.Add(isTypeOf, entityTypeMapping.LineInfo); } // create map from column name to condition var columnMap = entityTypeMapping.Conditions.ToDictionary( condition => condition.ColumnName, condition => condition); // align conditions with discriminator columns var columnMappings = new List (this.DiscriminatorColumns.Count); for (int i = 0; i < this.DiscriminatorColumns.Count; i++) { string discriminatorColumn = this.DiscriminatorColumns[i]; FunctionImportEntityTypeMappingCondition mappingCondition; if (columnMap.TryGetValue(discriminatorColumn, out mappingCondition)) { columnMappings.Add(mappingCondition); } else { // null indicates the value for this discriminator doesn't matter columnMappings.Add(null); } } // create bit map for implied entity types bool[] impliedEntityTypesBitMap = new bool[this.MappedEntityTypes.Count]; var impliedEntityTypesSet = new Set (entityTypeMapping.GetMappedEntityTypes(itemCollection)); for (int i = 0; i < this.MappedEntityTypes.Count; i++) { impliedEntityTypesBitMap[i] = impliedEntityTypesSet.Contains(this.MappedEntityTypes[i]); } // construct normalized mapping normalizedEntityTypeMappings.Add(new FunctionImportNormalizedEntityTypeMapping(this, columnMappings, new BitArray(impliedEntityTypesBitMap))); // construct the rename mappings by adding isTypeOf types and specific entity types to the corresponding lists foreach (var isOfType in entityTypeMapping.IsOfTypeEntityTypes) { if (!isOfTypeEntityTypeColumnsRenameMapping.Keys.Contains(isOfType)) { isOfTypeEntityTypeColumnsRenameMapping.Add(isOfType, entityTypeMapping.ColumnsRenameList); } else { foreach (var rename in entityTypeMapping.ColumnsRenameList) { isOfTypeEntityTypeColumnsRenameMapping[isOfType].Add(rename); } } } foreach (var entityType in entityTypeMapping.EntityTypes) { if (!entityTypeColumnsRenameMapping.Keys.Contains(entityType)) { entityTypeColumnsRenameMapping.Add(entityType, entityTypeMapping.ColumnsRenameList); } else { foreach (var rename in entityTypeMapping.ColumnsRenameList) { entityTypeColumnsRenameMapping[entityType].Add(rename); } } } } this.ReturnTypeColumnsRenameMapping = new FunctionImportReturnTypeEntityTypeColumnsRenameBuilder( isOfTypeEntityTypeColumnsRenameMapping, entityTypeColumnsRenameMapping).ColumnRenameMapping; this.NormalizedEntityTypeMappings = new OM.ReadOnlyCollection ( normalizedEntityTypeMappings); } else { // FunctionImportComplexTypeMapping Debug.Assert(structuralTypeMappings.First() is FunctionImportComplexTypeMapping, "only two types can have renames, complexType and entityType"); IEnumerable complexTypeMappings = structuralTypeMappings.Cast (); Debug.Assert(complexTypeMappings.Count() == 1, "how come there are more than 1, complex type cannot derive from other complex type"); this.ReturnTypeColumnsRenameMapping = new Dictionary (); foreach (var rename in complexTypeMappings.First().ColumnsRenameList) { FunctionImportReturnTypeStructuralTypeColumnRenameMapping columnRenameMapping = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(rename.CMember); columnRenameMapping.AddRename(new FunctionImportReturnTypeStructuralTypeColumn( rename.SColumn, complexTypeMappings.First().ReturnType, false)); this.ReturnTypeColumnsRenameMapping.Add(rename.CMember, columnRenameMapping); } // initialize the extra data this.NormalizedEntityTypeMappings = new System.Collections.ObjectModel.ReadOnlyCollection ( normalizedEntityTypeMappings); this.DiscriminatorColumns = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); this.MappedEntityTypes = new System.Collections.ObjectModel.ReadOnlyCollection (new List () { }); } } /// /// Gets store function (or target of the mapping) /// internal readonly EdmFunction TargetFunction; ////// Gets model function (or source of the mapping) /// internal readonly EdmFunction FunctionImport; ////// Gets all types in scope for this mapping. /// internal readonly OM.ReadOnlyCollectionMappedEntityTypes; /// /// Gets a list of all discriminator columns used in this mapping. /// internal readonly OM.ReadOnlyCollectionDiscriminatorColumns; /// /// Gets normalized representation of all EntityTypeMapping fragments for this /// function import mapping. /// internal readonly OM.ReadOnlyCollectionNormalizedEntityTypeMappings; /// /// Gets line infos for entity type mappings. /// internal readonly KeyToListMapEntityTypeLineInfos; /// /// Gets line infos for IsTypeOf mappings for entity types. /// internal readonly KeyToListMapIsTypeOfLineInfos; /// /// Get the columns rename mapping for return type, the first string is the member name /// the second one is column names for different types that mentioned in the mapping. /// internal readonly DictionaryReturnTypeColumnsRenameMapping; /// /// Given discriminator values (ordinally aligned with DiscriminatorColumns), determines /// the entity type to return. Throws a CommandExecutionException if the type is ambiguous. /// internal EntityType Discriminate(object[] discriminatorValues) { // initialize matching types bit map BitArray typeCandidates = new BitArray(this.MappedEntityTypes.Count, true); foreach (var typeMapping in this.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 = this.MappedEntityTypes[i]; } } // if there is no match, raise an exception if (null == entityType) { throw EntityUtil.CommandExecution(System.Data.Entity.Strings.ADP_InvalidDataReaderUnableToDetermineType); } return entityType; } ////// Determines which explicitly mapped types in the function import mapping cannot be generated. /// For IsTypeOf declarations, reports if no type in hierarchy can be produced. /// /// Works by: /// /// - Converting type mapping conditions into vertices /// - Checking that some assignment satisfies /// internal void GetUnreachableTypes(EdmItemCollection itemCollection, out KeyToListMapunreachableEntityTypes, out KeyToListMap unreachableIsTypeOfs) { // Contains, for each DiscriminatorColumn, a domain variable where the domain values are // integers representing the ordinal within discriminatorDomains DomainVariable [] variables = ConstructDomainVariables(); // Convert type mapping conditions to decision diagram vertices var converter = new DomainConstraintConversionContext (); Vertex[] mappingConditions = ConvertMappingConditionsToVertices(converter, variables); // Find reachable types Set reachableTypes = FindReachableTypes(converter, mappingConditions); CollectUnreachableTypes(itemCollection, reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs); } /// /// 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. /// ////// Requires that the given function import mapping refers to a Collection(Entity) or Collection(ComplexType) CSDL /// function. /// ///Row type. internal TypeUsage GetExpectedTargetResultType(MetadataWorkspace workspace) { // Collect all columns as name-type pairs. Dictionarycolumns = new Dictionary (); // Figure out which entity types we expect to yield from the function. IEnumerable structuralTypes; if (0 == this.NormalizedEntityTypeMappings.Count) { // No explicit type mappings; just use the type specified in the ReturnType attribute on the function. StructuralType structuralType; MetadataHelper.TryGetFunctionImportReturnType (this.FunctionImport, 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 = this.MappedEntityTypes.Cast (); } // 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.DiscriminatorColumns) { 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; } /// /// Determines which types are produced by this mapping /// private SetFindReachableTypes(DomainConstraintConversionContext converter, Vertex[] mappingConditions) { Set reachableTypes = new Set (); // for each entity type, create a candidate function that evaluates to true given // discriminator assignments iff. all of that type's conditions evaluate to true // and its negative conditions evaluate to false Vertex[] candidateFunctions = new Vertex[this.MappedEntityTypes.Count]; for (int i = 0; i < candidateFunctions.Length; i++) { // seed the candidate function conjunction with 'true' Vertex candidateFunction = Vertex.One; for (int j = 0; j < this.NormalizedEntityTypeMappings.Count; j++) { var entityTypeMapping = this.NormalizedEntityTypeMappings[j]; // determine if this mapping is a positive or negative case for the current type if (entityTypeMapping.ImpliedEntityTypes[i]) { candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]); } else { candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j])); } } candidateFunctions[i] = candidateFunction; } // for each type, make sure there is some assignment that resolves to only that type for (int i = 0; i < candidateFunctions.Length; i++) { // create a function that evaluates to true iff. the current candidate function is true // and every other candidate function is false Vertex isExactlyThisTypeCondition = converter.Solver.And( candidateFunctions.Select((typeCondition, ordinal) => ordinal == i ? typeCondition : converter.Solver.Not(typeCondition))); // if the above conjunction is satisfiable, it means some row configuration exists // producing the type if (!isExactlyThisTypeCondition.IsZero()) { reachableTypes.Add(this.MappedEntityTypes[i]); } } return reachableTypes; } private void CollectUnreachableTypes(EdmItemCollection itemCollection, Set reachableTypes, out KeyToListMap entityTypes, out KeyToListMap isTypeOfEntityTypes) { // Collect line infos for types in violation entityTypes = new KeyToListMap (EqualityComparer .Default); isTypeOfEntityTypes = new KeyToListMap (EqualityComparer .Default); if (reachableTypes.Count == this.MappedEntityTypes.Count) { // All types are reachable; nothing to check return; } // Find IsTypeOf mappings where no type in hierarchy can generate a row foreach (var isTypeOf in this.IsTypeOfLineInfos.Keys) { if (!MetadataHelper.GetTypeAndSubtypesOf(isTypeOf, itemCollection, false) .Cast () .Intersect(reachableTypes) .Any()) { // no type in the hierarchy is reachable... isTypeOfEntityTypes.AddRange(isTypeOf, this.IsTypeOfLineInfos.EnumerateValues(isTypeOf)); } } // Find explicit types not generating a value foreach (var entityType in this.EntityTypeLineInfos.Keys) { if (!reachableTypes.Contains(entityType)) { entityTypes.AddRange(entityType, this.EntityTypeLineInfos.EnumerateValues(entityType)); } } } private DomainVariable [] ConstructDomainVariables() { // determine domain for each discriminator column, including "other" and "null" placeholders var discriminatorDomains = new Set [this.DiscriminatorColumns.Count]; for (int i = 0; i < discriminatorDomains.Length; i++) { discriminatorDomains[i] = new Set (); discriminatorDomains[i].Add(ValueCondition.IsOther); discriminatorDomains[i].Add(ValueCondition.IsNull); } // collect all domain values foreach (var typeMapping in this.NormalizedEntityTypeMappings) { for (int i = 0; i < this.DiscriminatorColumns.Count; i++) { var discriminatorValue = typeMapping.ColumnConditions[i]; if (null != discriminatorValue && !discriminatorValue.ConditionValue.IsNotNullCondition) // NotNull is a special range (everything but IsNull) { discriminatorDomains[i].Add(discriminatorValue.ConditionValue); } } } var discriminatorVariables = new DomainVariable [discriminatorDomains.Length]; for (int i = 0; i < discriminatorVariables.Length; i++) { // domain variable is identified by the column name and takes all collected domain values discriminatorVariables[i] = new DomainVariable (this.DiscriminatorColumns[i], discriminatorDomains[i].MakeReadOnly()); } return discriminatorVariables; } private Vertex[] ConvertMappingConditionsToVertices(ConversionContext > converter, DomainVariable [] variables) { Vertex[] conditions = new Vertex[this.NormalizedEntityTypeMappings.Count]; for (int i = 0; i < conditions.Length; i++) { var typeMapping = this.NormalizedEntityTypeMappings[i]; // create conjunction representing the condition Vertex condition = Vertex.One; for (int j = 0; j < this.DiscriminatorColumns.Count; j++) { var columnCondition = typeMapping.ColumnConditions[j]; if (null != columnCondition) { var conditionValue = columnCondition.ConditionValue; if (conditionValue.IsNotNullCondition) { // the 'not null' condition is not actually part of the domain (since it // covers other elements), so create a Not(value in {null}) condition var isNull = new TermExpr >( new DomainConstraint (variables[j], ValueCondition.IsNull)); Vertex isNullVertex = converter.TranslateTermToVertex(isNull); condition = converter.Solver.And(condition, converter.Solver.Not(isNullVertex)); } else { var hasValue = new TermExpr >( new DomainConstraint (variables[j], conditionValue)); condition = converter.Solver.And(condition, converter.TranslateTermToVertex(hasValue)); } } } conditions[i] = condition; } return conditions; } } internal sealed class FunctionImportNormalizedEntityTypeMapping { internal FunctionImportNormalizedEntityTypeMapping(FunctionImportMapping parent, List columnConditions, BitArray impliedEntityTypes) { // validate arguments EntityUtil.CheckArgumentNull(parent, "parent"); EntityUtil.CheckArgumentNull(columnConditions, "discriminatorValues"); EntityUtil.CheckArgumentNull(impliedEntityTypes, "impliedEntityTypes"); Debug.Assert(columnConditions.Count == parent.DiscriminatorColumns.Count, "discriminator values must be ordinally aligned with discriminator columns"); Debug.Assert(impliedEntityTypes.Count == parent.MappedEntityTypes.Count, "implied entity types must be ordinally aligned with mapped entity types"); this.ColumnConditions = new OM.ReadOnlyCollection (columnConditions.ToList()); this.ImpliedEntityTypes = impliedEntityTypes; this.ComplementImpliedEntityTypes = (new BitArray(this.ImpliedEntityTypes)).Not(); } /// /// Gets discriminator values aligned with DiscriminatorColumns of the parent FunctionImportMapping. /// A null ValueCondition indicates 'anything goes'. /// internal readonly OM.ReadOnlyCollectionColumnConditions; /// /// Gets bit array with 'true' indicating the corresponding MappedEntityType of the parent /// FunctionImportMapping is implied by this fragment. /// internal readonly BitArray ImpliedEntityTypes; ////// Gets the complement of the ImpliedEntityTypes BitArray. /// internal readonly BitArray ComplementImpliedEntityTypes; public override string ToString() { return String.Format(CultureInfo.InvariantCulture, "Values={0}, Types={1}", StringUtil.ToCommaSeparatedString(this.ColumnConditions), StringUtil.ToCommaSeparatedString(this.ImpliedEntityTypes)); } } internal abstract class FunctionImportEntityTypeMappingCondition { protected FunctionImportEntityTypeMappingCondition(string columnName) { this.ColumnName = EntityUtil.CheckArgumentNull(columnName, "columnName"); } internal abstract ValueCondition ConditionValue { get; } internal readonly string ColumnName; internal abstract bool ColumnValueMatchesCondition(object columnValue); public override string ToString() { return this.ConditionValue.ToString(); } } internal sealed class FunctionImportEntityTypeMappingConditionValue : FunctionImportEntityTypeMappingCondition { internal FunctionImportEntityTypeMappingConditionValue(string columnName, XPathNavigator columnValue) : base(columnName) { this._xPathValue = EntityUtil.CheckArgumentNull(columnValue, "columnValue"); this._convertedValues = new Memoizer(this.GetConditionValue, null); } private readonly XPathNavigator _xPathValue; private readonly Memoizer _convertedValues; internal override ValueCondition ConditionValue { get { return new ValueCondition(_xPathValue.Value); } } internal override bool ColumnValueMatchesCondition(object columnValue) { if (null == columnValue || Convert.IsDBNull(columnValue)) { // only FunctionImportEntityTypeMappingConditionIsNull can match a null // column value return false; } Type columnValueType = columnValue.GetType(); // check if we've interpreted this column type yet object conditionValue = _convertedValues.Evaluate(columnValueType); return ByValueEqualityComparer.Default.Equals(columnValue, conditionValue); } private object GetConditionValue(Type columnValueType) { object conditionValue; // check that the type is supported PrimitiveType primitiveType; if (!ClrProviderManifest.Instance.TryGetPrimitiveType(columnValueType, out primitiveType) || !StorageMappingItemLoader.IsTypeSupportedForCondition(primitiveType.PrimitiveTypeKind)) { throw EntityUtil.CommandExecution(Strings.Mapping_FunctionImport_UnsupportedType( this.ColumnName, columnValueType.FullName)); } try { conditionValue = _xPathValue.ValueAs(columnValueType); } catch (FormatException) { throw EntityUtil.CommandExecution(Strings.Mapping_FunctionImport_ConditionValueTypeMismatch( StorageMslConstructs.FunctionImportMappingElement, this.ColumnName, columnValueType.FullName)); } return conditionValue; } } internal sealed class FunctionImportEntityTypeMappingConditionIsNull : FunctionImportEntityTypeMappingCondition { internal FunctionImportEntityTypeMappingConditionIsNull(string columnName, bool isNull) : base(columnName) { this.IsNull = isNull; } internal readonly bool IsNull; internal override ValueCondition ConditionValue { get { return IsNull ? ValueCondition.IsNull : ValueCondition.IsNotNull; } } internal override bool ColumnValueMatchesCondition(object columnValue) { bool valueIsNull = null == columnValue || Convert.IsDBNull(columnValue); return valueIsNull == this.IsNull; } } /// /// Represents a simple value condition of the form (value IS NULL), (value IS NOT NULL) /// or (value EQ X). Supports IEquatable(Of ValueCondition) so that equivalent conditions /// can be identified. /// internal class ValueCondition : IEquatable{ internal readonly string Description; internal readonly bool IsSentinel; internal const string IsNullDescription = "NULL"; internal const string IsNotNullDescription = "NOT NULL"; internal const string IsOtherDescription = "OTHER"; internal readonly static ValueCondition IsNull = new ValueCondition(IsNullDescription, true); internal readonly static ValueCondition IsNotNull = new ValueCondition(IsNotNullDescription, true); internal readonly static ValueCondition IsOther = new ValueCondition(IsOtherDescription, true); private ValueCondition(string description, bool isSentinel) { Description = description; IsSentinel = isSentinel; } internal ValueCondition(string description) : this(description, false) { } internal bool IsNotNullCondition { get { return object.ReferenceEquals(this, IsNotNull); } } public bool Equals(ValueCondition other) { return other.IsSentinel == this.IsSentinel && other.Description == this.Description; } public override int GetHashCode() { return Description.GetHashCode(); } public override string ToString() { return this.Description; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- LZCodec.cs
- MatrixAnimationBase.cs
- ArgumentNullException.cs
- DataObject.cs
- CryptoStream.cs
- PartialCachingControl.cs
- MonthCalendar.cs
- EdmItemError.cs
- XmlValueConverter.cs
- HeaderUtility.cs
- TypeReference.cs
- ScriptingRoleServiceSection.cs
- UdpReplyToBehavior.cs
- Compiler.cs
- PerformanceCounterCategory.cs
- WorkflowOperationContext.cs
- UIPermission.cs
- ImageSourceTypeConverter.cs
- Column.cs
- PropertyGridEditorPart.cs
- TextSelectionHighlightLayer.cs
- PenContext.cs
- BaseTemplateBuildProvider.cs
- PageAsyncTask.cs
- DataGridItemEventArgs.cs
- AssociationEndMember.cs
- ZipIOFileItemStream.cs
- Input.cs
- EventSetterHandlerConverter.cs
- TransformedBitmap.cs
- LinkConverter.cs
- WeakReference.cs
- IntSumAggregationOperator.cs
- WaitHandleCannotBeOpenedException.cs
- TaskFactory.cs
- XmlTextWriter.cs
- CustomWebEventKey.cs
- CurrencyWrapper.cs
- TypeDescriptionProvider.cs
- SqlUtils.cs
- EventLogReader.cs
- BufferedReceiveElement.cs
- _ConnectionGroup.cs
- WindowsListViewItem.cs
- InstanceNotFoundException.cs
- BitmapEffectDrawing.cs
- SymbolTable.cs
- hebrewshape.cs
- DataControlImageButton.cs
- GatewayDefinition.cs
- EntityDataSourceEntityTypeFilterItem.cs
- InvalidateEvent.cs
- ThicknessConverter.cs
- WebRequestModuleElement.cs
- TrustLevel.cs
- HTMLTagNameToTypeMapper.cs
- WSUtilitySpecificationVersion.cs
- MdImport.cs
- UIElement3D.cs
- ServerProtocol.cs
- QueueProcessor.cs
- NavigationPropertyEmitter.cs
- EntityConnectionStringBuilder.cs
- TextMetrics.cs
- validation.cs
- ColorPalette.cs
- ComboBox.cs
- SiteMapNodeCollection.cs
- TextDecorations.cs
- SharedUtils.cs
- CultureSpecificStringDictionary.cs
- Permission.cs
- FtpWebResponse.cs
- UserValidatedEventArgs.cs
- FlowDocumentPageViewerAutomationPeer.cs
- UpdateManifestForBrowserApplication.cs
- CopyAction.cs
- XmlQueryContext.cs
- Stack.cs
- ResourcesChangeInfo.cs
- QueryStringParameter.cs
- LocatorGroup.cs
- DataGridViewRowEventArgs.cs
- AttributeEmitter.cs
- TypedMessageConverter.cs
- OSFeature.cs
- TraceSwitch.cs
- PersonalizableAttribute.cs
- PageStatePersister.cs
- ResXResourceWriter.cs
- Region.cs
- ExceptionHandlers.cs
- MsmqIntegrationInputChannel.cs
- DataViewSettingCollection.cs
- storepermission.cs
- SerializationInfo.cs
- ProviderSettings.cs
- PackageProperties.cs
- MeshGeometry3D.cs
- ListBase.cs