internal StorageModificationFunctionMapping(
            EntitySetBase entitySet,
            EntityTypeBase entityType,
            EdmFunction function,
            IEnumerable<StorageModificationFunctionParameterBinding> parameterBindings,
            FunctionParameter rowsAffectedParameter,
            IEnumerable<StorageModificationFunctionResultBinding> resultBindings)
        {
            //Contract.Requires(entitySet != null);
            //Contract.Requires(function != null);
            //Contract.Requires(parameterBindings != null);

            Function = function;
            RowsAffectedParameter = rowsAffectedParameter;
            ParameterBindings = parameterBindings.ToList().AsReadOnly();
            if (null != resultBindings)
            {
                var bindings = resultBindings.ToList();
                if (0 < bindings.Count)
                {
                    ResultBindings = bindings.AsReadOnly();
                }
            }
            CollocatedAssociationSetEnds =
                GetReferencedAssociationSetEnds(entitySet as EntitySet, entityType as EntityType, parameterBindings)
                    .ToList()
                    .AsReadOnly();
        }
 /// <summary>
 /// Merge the discriminatorMap info we just found with what we've already found.
 /// 
 /// In practice, if either the current or the new map is from an OfTypeOnly view, we
 /// have to avoid the optimizations.
 /// 
 /// If we have a new map that is a superset of the current map, then we can just swap
 /// the new map for the current one.
 /// 
 /// If the current map is tha super set of the new one ther's nothing to do.
 /// 
 /// (Of course, if neither has changed, then we really don't need to look)
 /// </summary>
 internal void Merge(EntityTypeBase neededRootEntityType, bool includesSubtypes, ExplicitDiscriminatorMap discriminatorMap)
 {
     // If what we've found doesn't exactly match what we are looking for we have more work to do
     if (RootEntityType != neededRootEntityType
         || IncludesSubTypes != includesSubtypes)
     {
         if (!IncludesSubTypes
             || !includesSubtypes)
         {
             // If either the original or the new map is from an of-type-only view we can't
             // merge, we just have to not optimize this case.
             DiscriminatorMap = null;
         }
         if (TypeSemantics.IsSubTypeOf(RootEntityType, neededRootEntityType))
         {
             // we're asking for a super type of existing type, and what we had is a proper 
             // subset of it -we can replace the existing item.
             RootEntityType = neededRootEntityType;
             DiscriminatorMap = discriminatorMap;
         }
         if (!TypeSemantics.IsSubTypeOf(neededRootEntityType, RootEntityType))
         {
             // If either the original or the new map is from an of-type-only view we can't
             // merge, we just have to not optimize this case.
             DiscriminatorMap = null;
         }
     }
 }
 /// <summary>
 /// Constructs the name of the collection type
 /// </summary>
 /// <param name="entityTypeBase">The entity type base that this ref type refers to</param>
 /// <returns>The identity of the resulting ref type</returns>
 private static string GetIdentity(EntityTypeBase entityTypeBase)
 {
     StringBuilder builder = new StringBuilder(50);
     builder.Append("reference[");
     entityTypeBase.BuildIdentity(builder);
     builder.Append("]");
     return builder.ToString();
 }
 /// <summary>
 /// Returns all mapping fragments for the given entity set's types and their parent types.
 /// </summary>
  internal static IEnumerable<StorageTypeMapping> GetMappingsForEntitySetAndSuperTypes(StorageMappingItemCollection mappingCollection, EntityContainer container, EntitySetBase entitySet, EntityTypeBase childEntityType)
  {
      return MetadataHelper.GetTypeAndParentTypesOf(childEntityType, mappingCollection.EdmItemCollection, true /*includeAbstractTypes*/).SelectMany(
          edmType => 
              edmType.EdmEquals(childEntityType) ? 
                GetMappingsForEntitySetAndType(mappingCollection, container, entitySet, (edmType as EntityTypeBase))
              : GetIsTypeOfMappingsForEntitySetAndType(mappingCollection, container, entitySet, (edmType as EntityTypeBase), childEntityType)
          ).ToList();
  }
Exemple #5
0
        /// <summary>
        /// Creates generated view object for the combination of the <paramref name="setMapping"/>.Set and the <paramref name="type"/>. 
        /// This constructor is used for user-defined query views only.
        /// </summary>
        internal static bool TryParseUserSpecifiedView(StorageSetMapping setMapping,
                                                       EntityTypeBase type,
                                                       string eSQL,
                                                       bool includeSubtypes,
                                                       StorageMappingItemCollection mappingItemCollection,
                                                       ConfigViewGenerator config,
                                                       /*out*/ IList<EdmSchemaError> errors,
                                                       out GeneratedView generatedView)
        {
            bool failed = false;

            DbQueryCommandTree commandTree;
            DiscriminatorMap discriminatorMap;
            Exception parserException;
            if (!GeneratedView.TryParseView(eSQL, true, setMapping.Set, mappingItemCollection, config, out commandTree, out discriminatorMap, out parserException))
            {
                EdmSchemaError error = new EdmSchemaError(System.Data.Entity.Strings.Mapping_Invalid_QueryView2(setMapping.Set.Name, parserException.Message),
                                           (int)StorageMappingErrorCode.InvalidQueryView, EdmSchemaErrorSeverity.Error,
                                           setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition, parserException);
                errors.Add(error);
                failed = true;
            }
            else
            {
                Debug.Assert(commandTree != null, "commandTree not set after parsing the view");

                // Verify that all expressions appearing in the view are supported.
                foreach (var error in ViewValidator.ValidateQueryView(commandTree, setMapping, type, includeSubtypes))
                {
                    errors.Add(error);
                    failed = true;
                }

                // Verify that the result type of the query view is assignable to the element type of the entityset
                CollectionType queryResultType = (commandTree.Query.ResultType.EdmType) as CollectionType;
                if ((queryResultType == null) || (!setMapping.Set.ElementType.IsAssignableFrom(queryResultType.TypeUsage.EdmType)))
                {
                    EdmSchemaError error = new EdmSchemaError(System.Data.Entity.Strings.Mapping_Invalid_QueryView_Type(setMapping.Set.Name),
                                               (int)StorageMappingErrorCode.InvalidQueryViewResultType, EdmSchemaErrorSeverity.Error,
                                               setMapping.EntityContainerMapping.SourceLocation, setMapping.StartLineNumber, setMapping.StartLinePosition);
                    errors.Add(error);
                    failed = true;
                }
            }

            if (!failed)
            {
                generatedView = new GeneratedView(setMapping.Set, type, commandTree, eSQL, discriminatorMap, mappingItemCollection, config);
                return true;
            }
            else
            {
                generatedView = null;
                return false;
            }
        }
 /// <summary>
 /// Returns mappings for the given set/type only if the mapping applies also to childEntittyType either via IsTypeOf or explicitly specifying multiple types in mapping fragments.
 /// </summary>
 private static IEnumerable<StorageTypeMapping> GetIsTypeOfMappingsForEntitySetAndType(StorageMappingItemCollection mappingCollection, EntityContainer container, EntitySetBase entitySet, EntityTypeBase entityType, EntityTypeBase childEntityType)
 {
     foreach (var mapping in GetMappingsForEntitySetAndType(mappingCollection, container, entitySet, entityType))
     {
         if (mapping.IsOfTypes.Any(parentType => parentType.IsAssignableFrom(childEntityType)) || mapping.Types.Contains(childEntityType))
         {
             yield return mapping;
         }
     }
 }      
Exemple #7
0
        private void CreateAndAddNavigationProperty(StructuralType cspaceType, StructuralType ospaceType, NavigationProperty cspaceProperty, PropertyInfo clrProperty)
        {
            EdmType ospaceRelationship;

            if (SessionData.CspaceToOspace.TryGetValue(cspaceProperty.RelationshipType, out ospaceRelationship))
            {
                Debug.Assert(ospaceRelationship is StructuralType, "Structural type expected.");

                bool    foundTarget = false;
                EdmType targetType  = null;
                if (Helper.IsCollectionType(cspaceProperty.TypeUsage.EdmType))
                {
                    EdmType findType;
                    foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)((CollectionType)cspaceProperty.TypeUsage.EdmType).TypeUsage.EdmType, out findType);
                    if (foundTarget)
                    {
                        Debug.Assert(findType is StructuralType, "Structural type expected.");

                        targetType = findType.GetCollectionType();
                    }
                }
                else
                {
                    EdmType findType;
                    foundTarget = SessionData.CspaceToOspace.TryGetValue((StructuralType)cspaceProperty.TypeUsage.EdmType, out findType);
                    if (foundTarget)
                    {
                        Debug.Assert(findType is StructuralType, "Structural type expected.");

                        targetType = findType;
                    }
                }


                Debug.Assert(foundTarget, "Since the relationship will only be created if it can find the types for both ends, we will never fail to find one of the ends");

                NavigationProperty navigationProperty = new NavigationProperty(cspaceProperty.Name, TypeUsage.Create(targetType), clrProperty);
                navigationProperty.RelationshipType = (RelationshipType)ospaceRelationship;

                // we can use First because o-space relationships are created directly from
                // c-space relationship
                navigationProperty.ToEndMember   = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.ToEndMember.Name);
                navigationProperty.FromEndMember = (RelationshipEndMember)((RelationshipType)ospaceRelationship).Members.First(e => e.Name == cspaceProperty.FromEndMember.Name);
                ospaceType.AddMember(navigationProperty);
            }
            else
            {
                EntityTypeBase missingType = cspaceProperty.RelationshipType.RelationshipEndMembers.Select(e => ((RefType)e.TypeUsage.EdmType).ElementType).First(e => e != cspaceType);
                string         message     =
                    SessionData.LoadMessageLogger.CreateErrorMessageWithTypeSpecificLoadLogs(
                        Strings.Validator_OSpace_Convention_RelationshipNotLoaded(cspaceProperty.RelationshipType.FullName, missingType.FullName),
                        missingType);
                SessionData.EdmItemErrors.Add(new EdmItemError(message, ospaceType));
            }
        }
        internal static IEnumerable<StorageTypeMapping> GetMappingsForEntitySetAndType(StorageMappingItemCollection mappingCollection, EntityContainer container, EntitySetBase entitySet, EntityTypeBase entityType)
        {
            Debug.Assert(entityType != null, "EntityType parameter should not be null.");
            StorageEntityContainerMapping containerMapping = GetEntityContainerMap(mappingCollection, container);
            StorageSetMapping extentMap = containerMapping.GetSetMapping(entitySet.Name);

            //The Set may have no mapping
            if (extentMap != null)
            {
                //for each mapping fragment of Type we are interested in within the given set
                //Check use of IsOfTypes in Code review
                foreach (StorageTypeMapping typeMap in extentMap.TypeMappings.Where(map => map.Types.Union(map.IsOfTypes).Contains(entityType)))
                {
                    yield return typeMap;
                }
            }
        }
        internal static IEnumerable<StorageEntityTypeModificationFunctionMapping> GetModificationFunctionMappingsForEntitySetAndType(StorageMappingItemCollection mappingCollection, EntityContainer container, EntitySetBase entitySet, EntityTypeBase entityType)
        {
            StorageEntityContainerMapping containerMapping = GetEntityContainerMap(mappingCollection, container);

            StorageSetMapping extentMap = containerMapping.GetSetMapping(entitySet.Name);
            StorageEntitySetMapping entitySetMapping = extentMap as StorageEntitySetMapping;

            //The Set may have no mapping
            if (entitySetMapping != null)
            {
                if (entitySetMapping != null) //could be association set mapping
                {
                    foreach (var v in entitySetMapping.ModificationFunctionMappings.Where(functionMap => functionMap.EntityType.Equals(entityType)))
                    {
                        yield return v;
                    }
                }
            }

        }
        //----------------------------------------------------------------------------------------------
        // Possible Future Enhancement: revisit factoring of EntitySetBase and delta between C constructs and S constructs
        //
        // Currently, we need to have a way to map an entityset or a relationship set in S space
        // to the appropriate structures in the store. In order to address this we said we would
        // add new ItemAttributes (tableName, schemaName and catalogName to the EntitySetBase)... 
        // problem with this is that we are bleading a leaf-level, store specific set of constructs
        // into the object model for things that may exist at either C or S. 
        //
        // We need to do this for now to push forward on enabling the conversion but we need to re-examine
        // whether we should have separate C and S space constructs or some other mechanism for 
        // maintaining this metadata.
        //----------------------------------------------------------------------------------------------

        #region Constructors
        /// <summary>
        /// The constructor for constructing the EntitySet with a given name and an entity type
        /// </summary>
        /// <param name="name">The name of the EntitySet</param>
        /// <param name="schema">The db schema</param>
        /// <param name="table">The db table</param>
        /// <param name="definingQuery">The provider specific query that should be used to retrieve the EntitySet</param>
        /// <param name="entityType">The entity type of the entities that this entity set type contains</param>        
        /// <exception cref="System.ArgumentNullException">Thrown if the name or entityType argument is null</exception>
        internal EntitySetBase(string name, string schema, string table, string definingQuery, EntityTypeBase entityType)
        {
            EntityUtil.GenericCheckArgumentNull(entityType, "entityType");
            EntityUtil.CheckStringArgument(name, "name");
            // SQLBU 480236: catalogName, schemaName & tableName are allowed to be null, empty & non-empty

            _name = name;

            //---- name of the 'schema'
            //---- this is used by the SQL Gen utility to support generation of the correct name in the store
            _schema = schema;

            //---- name of the 'table'
            //---- this is used by the SQL Gen utility to support generation of the correct name in the store
            _table = table;

            //---- the Provider specific query to use to retrieve the EntitySet data
            _definingQuery = definingQuery;
            
            this.ElementType = entityType;
        }
 /// <summary>
 /// Get the rel properties declared by this type (and *not* by any of its subtypes)
 /// </summary>
 /// <param name="entityType">the entity type</param>
 /// <returns>set of rel properties declared for this type</returns>
 internal IEnumerable<RelProperty> GetDeclaredOnlyRelProperties(EntityTypeBase entityType)
 {
     List<RelProperty> relProperties;
     if (_relPropertyMap.TryGetValue(entityType, out relProperties))
     {
         foreach (RelProperty p in relProperties)
         {
             yield return p;
         }
     }
     yield break;
 }
        /// <summary>
        /// Return members for MetdataWorkspace.GetRequiredOriginalValueMembers() and MetdataWorkspace.GetRelevantMembersForUpdate() methods.
        /// </summary>
        /// <param name="entitySet">An EntitySet belonging to the C-Space. Must not be null.</param>
        /// <param name="entityType">An EntityType that participates in the given EntitySet. Must not be null.</param>
        /// <param name="interestingMembersKind">Scenario the members should be returned for.</param>
        /// <returns>ReadOnlyCollection of interesting members for the requested scenario (<paramref name="interestingMembersKind"/>).</returns>        
        internal ReadOnlyCollection<EdmMember> GetInterestingMembers(EntitySetBase entitySet, EntityTypeBase entityType, InterestingMembersKind interestingMembersKind)
        {
            Debug.Assert(entitySet != null, "entitySet != null");
            Debug.Assert(entityType != null, "entityType != null");

            var key = new Tuple<EntitySetBase, EntityTypeBase, InterestingMembersKind>(entitySet, entityType, interestingMembersKind);
            return _cachedInterestingMembers.GetOrAdd(key,  FindInterestingMembers(entitySet, entityType, interestingMembersKind));
        }
 internal static bool EntityTypeEquals(EntityTypeBase entityType1, EntityTypeBase entityType2)
 {
     return object.ReferenceEquals(entityType1, entityType2);
 }
        private ErrorLog GenerateQueryViewForExtentAndType(
            CqlIdentifiers identifiers, ViewSet views, EntitySetBase entity, EntityTypeBase type, ViewGenMode mode)
        {
            Debug.Assert(mode != ViewGenMode.GenerateAllViews);

            // Keep track of the mapping exceptions that we have generated
            var errorLog = new ErrorLog();

            if (m_config.IsViewTracing)
            {
                Helpers.StringTraceLine(String.Empty);
                Helpers.StringTraceLine(String.Empty);
                Helpers.FormatTraceLine(
                    "================= Generating {0} Query View for: {1} ===========================",
                    (mode == ViewGenMode.OfTypeViews) ? "OfType" : "OfTypeOnly",
                    entity.Name);
                Helpers.StringTraceLine(String.Empty);
                Helpers.StringTraceLine(String.Empty);
            }

            try
            {
                // (1) view generation (checks that extents are fully mapped)
                var context = CreateViewgenContext(entity, ViewTarget.QueryView, identifiers);
                var queryRewriter = GenerateViewsForExtentAndType(type, context, identifiers, views, mode);
            }
            catch (InternalMappingException exception)
            {
                // All exceptions have mapping errors in them
                Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception");
                errorLog.Merge(exception.ErrorLog);
            }

            return errorLog;
        }
        /// <summary>
        /// Entry point for Type specific generation of Query Views
        /// </summary>
        internal static ViewGenResults GenerateTypeSpecificQueryView(StorageEntityContainerMapping containerMapping,
                                                              ConfigViewGenerator config,
                                                              EntitySetBase entity,
                                                              EntityTypeBase type,
                                                              bool includeSubtypes,
                                                              out bool success)
        {
            EntityUtil.CheckArgumentNull(containerMapping, "containerMapping");
            EntityUtil.CheckArgumentNull(config, "config");
            EntityUtil.CheckArgumentNull(entity, "entity");
            EntityUtil.CheckArgumentNull(type, "type");
            Debug.Assert(!type.Abstract, "Can not generate OfType/OfTypeOnly query view for and abstract type");

            if (config.IsNormalTracing)
            {
                Helpers.StringTraceLine("");
                Helpers.StringTraceLine("<<<<<<<< Generating Query View for Entity [" + entity.Name + "] OfType" + (includeSubtypes ? "" : "Only") + "(" + type.Name + ") >>>>>>>");
            }

            if (containerMapping.GetEntitySetMapping(entity.Name).QueryView != null)
            {
                //Type-specific QV does not exist in the cache, but 
                // there is a EntitySet QV. So we can't generate the view (no mapping exists for this EntitySet)
                // and we rely on Query to call us again to get the EntitySet View.
                success = false;
                return null;
            }

            //Compute Cell Groups or get it from Memoizer
            InputForComputingCellGroups args = new InputForComputingCellGroups(containerMapping, config);
            OutputFromComputeCellGroups result = containerMapping.GetCellgroups(args);
            success = result.Success;

            if (!success)
            {
                return null;
            }

            List<ForeignConstraint> foreignKeyConstraints = result.ForeignKeyConstraints;
            // Get a Clone of cell groups from cache since cells are modified during viewgen, and we dont want the cached copy to change
            List<CellGroup> cellGroups = cellGroups = result.CellGroups.Select(setOfcells => new CellGroup(setOfcells.Select(cell => new Cell(cell)))).ToList();
            List<Cell> cells = result.Cells;
            CqlIdentifiers identifiers = result.Identifiers;


            ViewGenResults viewGenResults = new ViewGenResults();
            ErrorLog tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, config, containerMapping);
            if (tmpLog.Count > 0)
            {
                viewGenResults.AddErrors(tmpLog);
                Helpers.StringTraceLine(viewGenResults.ErrorsToString());
                success = true; //atleast we tried successfully
                return viewGenResults;
            }

            foreach (CellGroup cellGroup in cellGroups)
            {
                if (!DoesCellGroupContainEntitySet(cellGroup, entity))
                {
                    continue;
                }

                ViewGenerator viewGenerator = null;
                ErrorLog groupErrorLog = new ErrorLog();
                try
                {
                    viewGenerator = new ViewGenerator(cellGroup, config, foreignKeyConstraints, containerMapping);
                }
                catch (InternalMappingException exception)
                {
                    // All exceptions have mapping errors in them
                    Debug.Assert(exception.ErrorLog.Count > 0, "Incorrectly created mapping exception");
                    groupErrorLog = exception.ErrorLog;
                }

                if (groupErrorLog.Count > 0)
                {
                    break;
                }
                Debug.Assert(viewGenerator != null); //make sure there is no exception thrown that does not add error to log

                ViewGenMode mode = includeSubtypes ? ViewGenMode.OfTypeViews : ViewGenMode.OfTypeOnlyViews;

                groupErrorLog = viewGenerator.GenerateQueryViewForSingleExtent(viewGenResults.Views, identifiers, entity, type, mode);

                if (groupErrorLog.Count != 0)
                {
                    viewGenResults.AddErrors(groupErrorLog);
                }
            }

            success = true;
            return viewGenResults;
        }
 internal StorageModificationFunctionMapping(
     EntitySetBase entitySet,
     EntityTypeBase entityType,
     EdmFunction function,
     IEnumerable<StorageModificationFunctionParameterBinding> parameterBindings,
     FunctionParameter rowsAffectedParameter,
     IEnumerable<StorageModificationFunctionResultBinding> resultBindings)
 {
     EntityUtil.CheckArgumentNull(entitySet, "entitySet");
     this.Function = EntityUtil.CheckArgumentNull(function, "function");
     this.RowsAffectedParameter = rowsAffectedParameter;
     this.ParameterBindings = EntityUtil.CheckArgumentNull(parameterBindings, "parameterBindings")
         .ToList().AsReadOnly();
     if (null != resultBindings)
     {
         List<StorageModificationFunctionResultBinding> bindings = resultBindings.ToList();
         if (0 < bindings.Count)
         {
             ResultBindings = bindings.AsReadOnly();
         }
     }
     this.CollocatedAssociationSetEnds = GetReferencedAssociationSetEnds(entitySet as EntitySet, entityType as EntityType, parameterBindings)
         .ToList()
         .AsReadOnly();
 }
        internal ErrorLog GenerateQueryViewForSingleExtent(
            ViewSet views, CqlIdentifiers identifiers, EntitySetBase entity, EntityTypeBase type, ViewGenMode mode)
        {
            Debug.Assert(mode != ViewGenMode.GenerateAllViews);

            if (m_config.IsNormalTracing)
            {
                var builder = new StringBuilder();
                Cell.CellsToBuilder(builder, m_cellGroup);
                Helpers.StringTraceLine(builder.ToString());
            }

            // Check if the cellgroup is consistent and all known S constraints are
            // satisified by the known C constraints
            var validator = new CellGroupValidator(m_cellGroup, m_config);
            var errorLog = validator.Validate();
            if (errorLog.Count > 0)
            {
                errorLog.PrintTrace();
                return errorLog;
            }

            // Make sure that the foreign key constraints are not violated
            if (m_config.IsValidationEnabled)
            {
                CheckForeignKeyConstraints(errorLog);
            }

            if (errorLog.Count > 0)
            {
                errorLog.PrintTrace();
                return errorLog; // If we have discovered errors here, do not generate query views
            }

            // For the S-side, we add NOT ... for each scalar constant so
            // that if we have C, P in the mapping but the store has C, P, S,
            // we can handle it in the query views
            m_updateDomainMap.ExpandDomainsToIncludeAllPossibleValues();

            foreach (var cell in m_cellGroup)
            {
                cell.SQuery.WhereClause.FixDomainMap(m_updateDomainMap);
            }

            errorLog = GenerateQueryViewForExtentAndType(identifiers, views, entity, type, mode);

            return errorLog;
        }
 /// <summary>
 /// this method will be called in metadatworkspace, the signature is the same as the one in ViewDictionary
 /// </summary>
 /// <param name="workspace"></param>
 /// <param name="entity"></param>
 /// <param name="type"></param>
 /// <param name="includeSubtypes"></param>
 /// <param name="generatedView"></param>
 /// <returns></returns>
 internal bool TryGetGeneratedViewOfType(MetadataWorkspace workspace, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
 {
     return this.m_viewDictionary.TryGetGeneratedViewOfType(workspace, entity, type, includeSubtypes, out generatedView);
 }
 /// <summary>
 /// Finds foreign key properties and adds them to the <paramref name="interestingMembers"/>.
 /// </summary>
 /// <param name="entitySetBase">Entity set <paramref name="entityType"/> relates to. Must not be null.</param>
 /// <param name="entityType">Entity type for which to find foreign key properties. Must not be null.</param>
 /// <param name="interestingMembers">The list the interesting members (if any) will be added to. Must not be null.</param>
 private void FindForeignKeyProperties(EntitySetBase entitySetBase, EntityTypeBase entityType, List<EdmMember> interestingMembers)
 {
     var entitySet = entitySetBase as EntitySet;
     if (entitySet != null && entitySet.HasForeignKeyRelationships)
     {
         // (6) Foreign keys
         // select all foreign key properties defined on the entityType and all its ancestors
         interestingMembers.AddRange(
                 MetadataHelper.GetTypeAndParentTypesOf(entityType, this.m_edmCollection, true)
                 .SelectMany(e => ((EntityType)e).Properties)
                 .Where(p => entitySet.ForeignKeyDependents.SelectMany(fk => fk.Item2.ToProperties).Contains(p)));
     }
 }
 /// <summary>
 /// Tries to generate the Oftype or OfTypeOnly query view for a given entity set and type. 
 /// Returns false if the view could not be generated.
 /// Possible reasons for failing are 
 ///   1) Passing in OfTypeOnly on an abstract type
 ///   2) In user-specified query views mode a query for the given type is absent
 /// </summary>
 internal bool TryGetGeneratedViewOfType(
     EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
 {
     var key = new OfTypeQVCacheKey(entity, new Pair<EntityTypeBase, bool>(type, includeSubtypes));
     generatedView = m_generatedViewOfTypeMemoizer.Evaluate(key);
     return (generatedView != null);
 }
 internal DiscriminatorMapInfo(EntityTypeBase rootEntityType, bool includesSubTypes, ExplicitDiscriminatorMap discriminatorMap)
 {
     RootEntityType = rootEntityType;
     IncludesSubTypes = includesSubTypes;
     DiscriminatorMap = discriminatorMap;
 }
        /// <summary>
        /// If the discrminator map we're already tracking for this type (in this entityset)
        /// isn't already rooted at our required type, then we have to suppress the use of 
        /// the descriminator maps when we constrct the structuredtypes; see SQLBUDT #615744
        /// </summary>
        private void DetermineDiscriminatorMapUsage(
            Node viewNode, EntitySetBase entitySet, EntityTypeBase rootEntityType, bool includeSubtypes)
        {
            ExplicitDiscriminatorMap discriminatorMap = null;

            // we expect the view to be capped with a project; we're just being careful here.
            if (viewNode.Op.OpType
                == OpType.Project)
            {
                var discriminatedNewEntityOp = viewNode.Child1.Child0.Child0.Op as DiscriminatedNewEntityOp;

                if (null != discriminatedNewEntityOp)
                {
                    discriminatorMap = discriminatedNewEntityOp.DiscriminatorMap;
                }
            }

            DiscriminatorMapInfo discriminatorMapInfo;
            if (!m_discriminatorMaps.TryGetValue(entitySet, out discriminatorMapInfo))
            {
                if (null == rootEntityType)
                {
                    rootEntityType = entitySet.ElementType;
                    includeSubtypes = true;
                }
                discriminatorMapInfo = new DiscriminatorMapInfo(rootEntityType, includeSubtypes, discriminatorMap);
                m_discriminatorMaps.Add(entitySet, discriminatorMapInfo);
            }
            else
            {
                discriminatorMapInfo.Merge(rootEntityType, includeSubtypes, discriminatorMap);
            }
        }
            /// <summary>
            /// Generates a single query view for a given Extent and type. It is used to generate OfType and OfTypeOnly views.
            /// </summary>
            /// <param name="includeSubtypes">Whether the view should include extents that are subtypes of the given entity</param>
            private bool TryGenerateQueryViewOfType(EntityContainer entityContainer, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
            {
                Debug.Assert(entityContainer != null);
                Debug.Assert(entity != null);
                Debug.Assert(type != null);

                if (type.Abstract)
                {
                    generatedView = null;
                    return false;
                }

                //Get the mapping that has the entity container mapped.
                StorageEntityContainerMapping entityContainerMap = MappingMetadataHelper.GetEntityContainerMap(m_storageMappingItemCollection, entityContainer);
                Debug.Assert(!entityContainerMap.IsEmpty, "There are no entity set maps");

                bool success;
                ViewGenResults viewGenResults = ViewgenGatekeeper.GenerateTypeSpecificQueryView(entityContainerMap, m_config, entity, type, includeSubtypes, out success);
                if (!success)
                {
                    generatedView = null;
                    return false; //could not generate view
                }

                KeyToListMap<EntitySetBase, GeneratedView> extentMappingViews = viewGenResults.Views;

                if (viewGenResults.HasErrors)
                {
                    throw new MappingException(Helper.CombineErrorMessage(viewGenResults.Errors));
                }

                Debug.Assert(extentMappingViews.AllValues.Count() == 1, "Viewgen should have produced only one view");
                generatedView = extentMappingViews.AllValues.First();

                return true;
            }
 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;
     }
 }
        /// <summary>
        /// Get the rel-properties of this entity and its supertypes (starting from the root)
        /// </summary>
        /// <param name="entityType">the entity type</param>
        /// <returns>set of rel-properties for this entity type (and its supertypes)</returns>
        internal IEnumerable<RelProperty> GetRelProperties(EntityTypeBase entityType)
        {
            if (entityType.BaseType != null)
            {
                foreach (RelProperty p in GetRelProperties(entityType.BaseType as EntityTypeBase))
                {
                    yield return p;
                }
            }

            foreach (RelProperty p in GetDeclaredOnlyRelProperties(entityType))
            {
                yield return p;
            }

        }
        /// <summary>
        /// Finds interesting members for MetdataWorkspace.GetRequiredOriginalValueMembers() and MetdataWorkspace.GetRelevantMembersForUpdate() methods
        /// for the given <paramref name="entitySet"/> and <paramref name="entityType"/>.
        /// </summary>
        /// <param name="entitySet">An EntitySet belonging to the C-Space. Must not be null.</param>
        /// <param name="entityType">An EntityType that participates in the given EntitySet. Must not be null.</param>
        /// <param name="interestingMembersKind">Scenario the members should be returned for.</param>
        /// <returns>ReadOnlyCollection of interesting members for the requested scenario (<paramref name="interestingMembersKind"/>).</returns>        
        private ReadOnlyCollection<EdmMember> FindInterestingMembers(EntitySetBase entitySet, EntityTypeBase entityType, InterestingMembersKind interestingMembersKind)
        {
            Debug.Assert(entitySet != null, "entitySet != null");
            Debug.Assert(entityType != null, "entityType != null");

            var interestingMembers = new List<EdmMember>();

            foreach (var storageTypeMapping in MappingMetadataHelper.GetMappingsForEntitySetAndSuperTypes(this, entitySet.EntityContainer, entitySet, entityType))
            {
                StorageAssociationTypeMapping associationTypeMapping = storageTypeMapping as StorageAssociationTypeMapping;
                if (associationTypeMapping != null)
                {
                    FindInterestingAssociationMappingMembers(associationTypeMapping, interestingMembers);
                }
                else
                {
                    Debug.Assert(storageTypeMapping is StorageEntityTypeMapping, "StorageEntityTypeMapping expected.");

                    FindInterestingEntityMappingMembers((StorageEntityTypeMapping)storageTypeMapping, interestingMembersKind, interestingMembers);
                }
            }

            // For backwards compatibility we don't return foreign keys from the obsolete MetadataWorkspace.GetRequiredOriginalValueMembers() method
            if (interestingMembersKind != InterestingMembersKind.RequiredOriginalValueMembers)
            {
                FindForeignKeyProperties(entitySet, entityType, interestingMembers);
            }

            foreach (var functionMappings in MappingMetadataHelper
                                                .GetModificationFunctionMappingsForEntitySetAndType(this, entitySet.EntityContainer, entitySet, entityType)
                                                .Where(functionMappings => functionMappings.UpdateFunctionMapping != null))
            {
                FindInterestingFunctionMappingMembers(functionMappings, interestingMembersKind, ref interestingMembers);
            }

            Debug.Assert(interestingMembers != null, "interestingMembers must never be null.");

            return new ReadOnlyCollection<EdmMember>(interestingMembers.Distinct().ToList());
        }
 protected override void Visit(EntityTypeBase entityTypeBase)
 {
     base.Visit(entityTypeBase);
 }
 /// <summary>
 /// Tries to generate the Oftype or OfTypeOnly query view for a given entity set and type. 
 /// Returns false if the view could not be generated.
 /// Possible reasons for failing are 
 ///   1) Passing in OfTypeOnly on an abstract type
 ///   2) In user-specified query views mode a query for the given type is absent
 /// </summary>
 internal bool TryGetGeneratedViewOfType(MetadataWorkspace workspace, EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
 {
     OfTypeQVCacheKey key = new OfTypeQVCacheKey(entity, new Pair<EntityTypeBase, bool>(type, includeSubtypes));
     generatedView = this.m_generatedViewOfTypeMemoizer.Evaluate(key);
     return (generatedView != null);
 }
        private static EdmProperty[] GetProperties(EntityTypeBase entityType, IList<Som.PropertyRefElement> properties)
        {
            Debug.Assert(properties.Count != 0);
            EdmProperty[] result = new EdmProperty[properties.Count];

            for (int i = 0; i < properties.Count; i++)
            {
                result[i] = (EdmProperty)entityType.Members[properties[i].Name];
            }

            return result;
        }
 /// <summary>
 /// this method will be called in metadatworkspace, the signature is the same as the one in ViewDictionary
 /// </summary>
 /// <param name="entity"></param>
 /// <param name="type"></param>
 /// <param name="includeSubtypes"></param>
 /// <param name="generatedView"></param>
 /// <returns></returns>
 internal bool TryGetGeneratedViewOfType(
     EntitySetBase entity, EntityTypeBase type, bool includeSubtypes, out GeneratedView generatedView)
 {
     return m_viewDictionary.TryGetGeneratedViewOfType(entity, type, includeSubtypes, out generatedView);
 }