/// <summary> /// This method attempts to determine if the specified table has an integer /// primary key (i.e. "rowid"). If so, it sets the /// <paramref name="primaryKeyMember" /> parameter to the right /// <see cref="EdmMember" />; otherwise, the /// <paramref name="primaryKeyMember" /> parameter is set to null. /// </summary> /// <param name="table">The table to check.</param> /// <param name="keyMembers"> /// The collection of key members. An attempt is always made to set this /// parameter to a valid value. /// </param> /// <param name="primaryKeyMember"> /// The <see cref="EdmMember" /> that represents the integer primary key /// -OR- null if no such <see cref="EdmMember" /> exists. /// </param> /// <returns> /// Non-zero if the specified table has an integer primary key. /// </returns> private static bool IsIntegerPrimaryKey( EntitySetBase table, out ReadOnlyMetadataCollection<EdmMember> keyMembers, out EdmMember primaryKeyMember ) { keyMembers = table.ElementType.KeyMembers; if (keyMembers.Count == 1) /* NOTE: The "rowid" only? */ { EdmMember keyMember = keyMembers[0]; PrimitiveTypeKind typeKind; if (MetadataHelpers.TryGetPrimitiveTypeKind( keyMember.TypeUsage, out typeKind) && (typeKind == PrimitiveTypeKind.Int64)) { primaryKeyMember = keyMember; return true; } } primaryKeyMember = null; return false; }
internal ExtentPair(EntitySetBase acExtent, EntitySetBase asExtent) { cExtent = acExtent; sExtent = asExtent; }
private string GetTableName(Type type) { EntitySetBase es = GetEntitySet(type); return(string.Format("[{0}].[{1}]", es.MetadataProperties["Schema"].Value, es.MetadataProperties["Table"].Value)); }
/// <summary> /// Determines whether the given member maps to a column participating in an isnull /// condition. Useful to determine if a nullability constraint violation is going to /// cause roundtripping problems (e.g. if type is based on nullability of a 'non-nullable' /// property of a derived entity type) /// </summary> internal bool IsNullConditionMember(EntitySetBase entitySetBase, MetadataWorkspace workspace, EdmMember member) { return(SyncContains(entitySetBase, workspace, m_isNullConditionProperties, member)); }
public static string GetExtentKey(EntitySetBase entitySet) { return($"{entitySet.EntityContainer.Name}.{entitySet.Name}"); }
// Loads and registers any function mapping translators for the given extent (and related container) private void InitializeFunctionMappingTranslators(EntitySetBase entitySetBase, StorageEntityContainerMapping mapping) { var requiredEnds = new KeyToListMap <AssociationSet, AssociationEndMember>( EqualityComparer <AssociationSet> .Default); // see if function mapping metadata needs to be processed if (!m_functionMappingTranslators.ContainsKey(entitySetBase)) { // load all function mapping data from the current entity container foreach (StorageEntitySetMapping entitySetMapping in mapping.EntitySetMaps) { if (0 < entitySetMapping.ModificationFunctionMappings.Count) { // register the function mapping m_functionMappingTranslators.Add( entitySetMapping.Set, ModificationFunctionMappingTranslator.CreateEntitySetTranslator(entitySetMapping)); // register "null" function translators for all implicitly mapped association sets foreach (var end in entitySetMapping.ImplicitlyMappedAssociationSetEnds) { var associationSet = end.ParentAssociationSet; if (!m_functionMappingTranslators.ContainsKey(associationSet)) { m_functionMappingTranslators.Add( associationSet, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(null)); } // Remember that the current entity set is required for all updates to the collocated // relationship set. This entity set's end is opposite the target end for the mapping. var oppositeEnd = MetadataHelper.GetOppositeEnd(end); requiredEnds.Add(associationSet, oppositeEnd.CorrespondingAssociationEndMember); } } else { // register null translator (so that we never attempt to process this extent again) m_functionMappingTranslators.Add(entitySetMapping.Set, null); } } foreach (StorageAssociationSetMapping associationSetMapping in mapping.RelationshipSetMaps) { if (null != associationSetMapping.ModificationFunctionMapping) { var set = (AssociationSet)associationSetMapping.Set; // use indexer rather than Add since the association set may already have an implicit function // mapping -- this explicit function mapping takes precedence in such cases m_functionMappingTranslators.Add( set, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(associationSetMapping)); // remember that we've seen a function mapping for this association set, which overrides // any other behaviors for determining required/optional ends requiredEnds.AddRange(set, Enumerable.Empty <AssociationEndMember>()); } else { if (!m_functionMappingTranslators.ContainsKey(associationSetMapping.Set)) { // register null translator (so that we never attempt to process this extent again) m_functionMappingTranslators.Add(associationSetMapping.Set, null); } } } } // register association metadata for all association sets encountered foreach (var associationSet in requiredEnds.Keys) { m_associationSetMetadata.Add( associationSet, new AssociationSetMetadata( requiredEnds.EnumerateValues(associationSet))); } }
/// <summary> /// Returns store tables affected by modifications to a particular C-layer extent. Although this /// information can be inferred from the update view, we want to avoid compiling or loading /// views when not required. This information can be directly determined from mapping metadata. /// </summary> /// <param name="extent"> C-layer extent. </param> /// <returns> Affected store tables. </returns> internal Set <EntitySet> GetAffectedTables(EntitySetBase extent, MetadataWorkspace workspace) { return(SyncGetValue(extent, workspace, m_affectedTables, extent)); }
/// <summary> /// Marks the specified entity set as affected by the transaction. /// </summary> /// <param name="entitySet">The entity set.</param> public void AddAffectedEntitySet(EntitySetBase entitySet) { this.affectedEntitySets.Add(entitySet); }
protected virtual EntitySetBase VisitEntitySet(EntitySetBase entitySet) { return(entitySet); }
/// <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> /// Construct the new StorageSetMapping object. /// </summary> /// <param name="extent"> Extent metadata object </param> /// <param name="entityContainerMapping"> The EntityContainer mapping that contains this extent mapping </param> internal StorageSetMapping(EntitySetBase extent, StorageEntityContainerMapping entityContainerMapping) { m_entityContainerMapping = entityContainerMapping; m_extent = extent; m_typeMappings = new List <StorageTypeMapping>(); }
/// <summary> /// Calls the view dictionary to load the view, see detailed comments in the view dictionary class. /// </summary> internal GeneratedView GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace) { return(this.m_viewDictionary.GetGeneratedView(extent, workspace, this)); }
/// <summary> /// GetAuditRecordsForChange /// </summary> /// <param name="dbEntry"></param> /// <param name="user"></param> /// <returns></returns> private List <Audit> GetAuditRecordsForChange(DbEntityEntry dbEntry, int userId, bool insertSpecial = false) { var manager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager; EntitySetBase setBase = manager.GetObjectStateEntry(dbEntry.Entity).EntitySet; string[] keyNames = setBase.ElementType.KeyMembers.Select(k => k.Name).ToArray(); string keyName = keyNames.FirstOrDefault(); List <Audit> result = new List <Audit>(); string tableName = string.Empty; tableName = ObjectContext.GetObjectType(dbEntry.Entity.GetType()).Name; if (dbEntry.Entity.GetType().GetProperties().SingleOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Any()) != null) { keyName = dbEntry.Entity.GetType().GetProperties().SingleOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Any()).Name; } if (dbEntry.State == System.Data.EntityState.Added || insertSpecial) { // For Inserts, just add the whole record // If the entity implements IDescribableEntity, use the description from Describe(), otherwise use ToString() foreach (string propertyName in dbEntry.CurrentValues.PropertyNames) { result.Add(new Audit() { AuditID = Guid.NewGuid(), LoginID = userId, DateTime = DateTime.Now, Action = "A", // Added TableName = tableName, PrimaryKey = string.IsNullOrEmpty(keyName) ? keyName : dbEntry.CurrentValues.GetValue <object>(keyName).ToString(), // Again, adjust this if you have a multi-column key ColumnName = propertyName, // Or make it nullable, whatever you want NewValue = dbEntry.CurrentValues.GetValue <object>(propertyName) == null ? null : dbEntry.CurrentValues.GetValue <object>(propertyName).ToString(), // NewValue = dbEntry.CurrentValues.ToObject().ToString(), HubID = 1, //TODO: fix this partion id PartitionId = 0 } ); } } else if (dbEntry.State == System.Data.EntityState.Deleted) { foreach (string propertyName in dbEntry.OriginalValues.PropertyNames) { result.Add(new Audit() { AuditID = Guid.NewGuid(), LoginID = userId, DateTime = DateTime.Now, Action = "D", // Deleted TableName = tableName, PrimaryKey = string.IsNullOrEmpty(keyName) ? keyName : dbEntry.OriginalValues.GetValue <object>(keyName).ToString(), ColumnName = propertyName, OldValue = dbEntry.OriginalValues.GetValue <object>(propertyName) == null ? null : dbEntry.OriginalValues.GetValue <object>(propertyName).ToString(), NewValue = DBNull.Value.ToString(), HubID = 1, //TODO: fix this partion id PartitionId = 0 } ); } // Same with deletes, do the whole record, and use either the description from Describe() or ToString() } else if (dbEntry.State == System.Data.EntityState.Modified) { foreach (string propertyName in dbEntry.OriginalValues.PropertyNames) { // For updates, we only want to capture the columns that actually changed if (!object.Equals(dbEntry.OriginalValues.GetValue <object>(propertyName), dbEntry.CurrentValues.GetValue <object>(propertyName))) { result.Add(new Audit() { AuditID = Guid.NewGuid(), LoginID = userId, DateTime = DateTime.Now, Action = "M", // Modified TableName = tableName, PrimaryKey = string.IsNullOrEmpty(keyName) ? keyName : dbEntry.OriginalValues.GetValue <object>(keyName).ToString(), ColumnName = propertyName, OldValue = dbEntry.OriginalValues.GetValue <object>(propertyName) == null ? null : dbEntry.OriginalValues.GetValue <object>(propertyName).ToString(), NewValue = dbEntry.CurrentValues.GetValue <object>(propertyName) == null ? null : dbEntry.CurrentValues.GetValue <object>(propertyName).ToString(), HubID = 1, //TODO: fix this partion id PartitionId = 0 } ); } } } // Otherwise, don't do anything, we don't care about Unchanged or Detached entities return(result); }
internal ExtractorMetadata(EntitySetBase entitySetBase, StructuralType type, UpdateTranslator translator) { DebugCheck.NotNull(entitySetBase); DebugCheck.NotNull(type); DebugCheck.NotNull(translator); m_type = type; m_translator = translator; EntityType entityType = null; Set <EdmMember> keyMembers; Set <EdmMember> foreignKeyMembers; switch (type.BuiltInTypeKind) { case BuiltInTypeKind.RowType: // for row types (which are actually association end key records in disguise), all members // are keys keyMembers = new Set <EdmMember>(((RowType)type).Properties).MakeReadOnly(); foreignKeyMembers = Set <EdmMember> .Empty; break; case BuiltInTypeKind.EntityType: entityType = (EntityType)type; keyMembers = new Set <EdmMember>(entityType.KeyMembers).MakeReadOnly(); foreignKeyMembers = new Set <EdmMember>( ((EntitySet)entitySetBase).ForeignKeyDependents .SelectMany(fk => fk.Item2.ToProperties)).MakeReadOnly(); break; default: keyMembers = Set <EdmMember> .Empty; foreignKeyMembers = Set <EdmMember> .Empty; break; } var members = TypeHelpers.GetAllStructuralMembers(type); m_memberMap = new MemberInformation[members.Count]; // for each member, cache expensive to compute metadata information for (var ordinal = 0; ordinal < members.Count; ordinal++) { var member = members[ordinal]; // figure out flags for this member var flags = PropagatorFlags.NoFlags; var entityKeyOrdinal = default(int?); if (keyMembers.Contains(member)) { flags |= PropagatorFlags.Key; if (null != entityType) { entityKeyOrdinal = entityType.KeyMembers.IndexOf(member); } } if (foreignKeyMembers.Contains(member)) { flags |= PropagatorFlags.ForeignKey; } if (MetadataHelper.GetConcurrencyMode(member) == ConcurrencyMode.Fixed) { flags |= PropagatorFlags.ConcurrencyValue; } // figure out whether this member is mapped to any server generated // columns in the store var isServerGenerated = m_translator.ViewLoader.IsServerGen(entitySetBase, m_translator.MetadataWorkspace, member); // figure out whether member nullability is used as a condition in mapping var isNullConditionMember = m_translator.ViewLoader.IsNullConditionMember( entitySetBase, m_translator.MetadataWorkspace, member); // add information about this member m_memberMap[ordinal] = new MemberInformation( ordinal, entityKeyOrdinal, flags, member, isServerGenerated, isNullConditionMember); } }
public override DbMappingView GetView(EntitySetBase extent) { throw new NotImplementedException(); }
private ViewSimplifier(EntitySetBase viewTarget) { extent = viewTarget; }
private void InitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace) { var mapping = (StorageEntityContainerMapping)m_mappingCollection.GetMap(entitySetBase.EntityContainer); // make sure views have been generated for this sub-graph (trigger generation of the sub-graph // by retrieving a view for one of its components; not actually using the view here) if (mapping.HasViews) { m_mappingCollection.GetGeneratedView(entitySetBase, workspace); } var affectedTables = new Set <EntitySet>(); if (null != mapping) { var isNullConditionColumns = new Set <EdmMember>(); // find extent in the container mapping StorageSetMapping setMapping; if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { setMapping = mapping.GetEntitySetMapping(entitySetBase.Name); // Check for members that have result bindings in a function mapping. If a // function returns the member values, it indicates they are server-generated m_serverGenProperties.Unite(GetMembersWithResultBinding((StorageEntitySetMapping)setMapping)); } else if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { setMapping = mapping.GetRelationshipSetMapping(entitySetBase.Name); } else { Debug.Fail("unexpected extent type " + entitySetBase.BuiltInTypeKind); throw new NotSupportedException(); } // gather interesting tables, columns and properties from mapping fragments foreach (var mappingFragment in GetMappingFragments(setMapping)) { affectedTables.Add(mappingFragment.TableSet); // get all property mappings to figure out if anything is server generated m_serverGenProperties.AddRange(FindServerGenMembers(mappingFragment)); // get all columns participating in is null conditions isNullConditionColumns.AddRange(FindIsNullConditionColumns(mappingFragment)); } if (0 < isNullConditionColumns.Count) { // gather is null condition properties based on is null condition columns foreach (var mappingFragment in GetMappingFragments(setMapping)) { m_isNullConditionProperties.AddRange(FindPropertiesMappedToColumns(isNullConditionColumns, mappingFragment)); } } } m_affectedTables.Add(entitySetBase, affectedTables.MakeReadOnly()); InitializeFunctionMappingTranslators(entitySetBase, mapping); // for association sets, initialize AssociationSetMetadata if no function has claimed ownership // of the association yet if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { var associationSet = (AssociationSet)entitySetBase; if (!m_associationSetMetadata.ContainsKey(associationSet)) { m_associationSetMetadata.Add( associationSet, new AssociationSetMetadata( m_affectedTables[associationSet], associationSet, workspace)); } } }
private static string Identity(EntitySetBase entitySet) { return(entitySet.ToString()); }
/// <summary> /// For a given extent, returns the function mapping translator. /// </summary> /// <param name="extent"> Association set or entity set for which to retrieve a translator </param> /// <returns> Function translator or null if none exists for this extent </returns> internal ModificationFunctionMappingTranslator GetFunctionMappingTranslator(EntitySetBase extent, MetadataWorkspace workspace) { return(SyncGetValue(extent, workspace, m_functionMappingTranslators, extent)); }
private void TypeGeneratedEventHandler(object sender, TypeGeneratedEventArgs eventArgs) { if (!this.UseDataServiceCollection) { return; } if (eventArgs.TypeSource.BuiltInTypeKind != BuiltInTypeKind.EntityType && eventArgs.TypeSource.BuiltInTypeKind != BuiltInTypeKind.ComplexType) { return; } if (eventArgs.TypeSource.BuiltInTypeKind == BuiltInTypeKind.EntityType) { // Generate EntitySetAttribute only if there is exactly one entity set associated // with the entity type. The DataServiceEntitySetAttribute is not generated for ComplexType(s). EntitySetBase entitySet = this.GetUniqueEntitySetForType((EntityType)eventArgs.TypeSource); if (entitySet != null) { List <CodeAttributeDeclaration> additionalAttributes = eventArgs.AdditionalAttributes; CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(System.Data.Services.Common.EntitySetAttribute), CodeTypeReferenceOptions.GlobalReference), new CodeAttributeArgument(new CodePrimitiveExpression(entitySet.Name))); additionalAttributes.Add(attribute); } } //// Determine if type being generated has a base type if (eventArgs.BaseType != null && !String.IsNullOrEmpty(eventArgs.BaseType.BaseType)) { if (this.GetSourceTypes().Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).Where(x => ((EntityType)x).Name == eventArgs.BaseType.BaseType).Count() != 0) { //// Don't generate the PropertyChanged event and OnPropertyChanged method for derived type classes return; } } //// Add the INotifyPropertyChanged interface List <Type> additionalInterfaces = eventArgs.AdditionalInterfaces; additionalInterfaces.Add(typeof(System.ComponentModel.INotifyPropertyChanged)); //// Add the implementation of the INotifyPropertyChanged interface //// Generate this code: //// //// CSharp: //// //// public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; //// //// protected virtual void OnPropertyChanged(string property) { //// if ((this.PropertyChanged != null)) { //// this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property)); //// } //// } //// //// Visual Basic: //// //// Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged //// Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) //// If (Not (Me.PropertyChangedEvent) Is Nothing) Then //// RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property])) //// End If //// End Sub CodeMemberEvent propertyChangedEvent = new CodeMemberEvent(); propertyChangedEvent.Type = new CodeTypeReference(typeof(System.ComponentModel.PropertyChangedEventHandler), CodeTypeReferenceOptions.GlobalReference); propertyChangedEvent.Name = "PropertyChanged"; propertyChangedEvent.Attributes = MemberAttributes.Public; propertyChangedEvent.ImplementationTypes.Add(typeof(System.ComponentModel.INotifyPropertyChanged)); AttributeEmitter.AddGeneratedCodeAttribute(propertyChangedEvent); eventArgs.AdditionalMembers.Add(propertyChangedEvent); CodeMemberMethod propertyChangedMethod = new CodeMemberMethod(); propertyChangedMethod.Name = "OnPropertyChanged"; propertyChangedMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(System.String), CodeTypeReferenceOptions.GlobalReference), "property")); propertyChangedMethod.ReturnType = new CodeTypeReference(typeof(void)); AttributeEmitter.AddGeneratedCodeAttribute(propertyChangedMethod); propertyChangedMethod.Statements.Add( new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeEventReferenceExpression(new CodeThisReferenceExpression(), "PropertyChanged"), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), new CodeExpressionStatement( new CodeDelegateInvokeExpression( new CodeEventReferenceExpression(new CodeThisReferenceExpression(), "PropertyChanged"), new CodeExpression[] { new CodeThisReferenceExpression(), new CodeObjectCreateExpression(new CodeTypeReference(typeof(System.ComponentModel.PropertyChangedEventArgs), CodeTypeReferenceOptions.GlobalReference), new CodeArgumentReferenceExpression("property")) })))); propertyChangedMethod.Attributes = MemberAttributes.Family; eventArgs.AdditionalMembers.Add(propertyChangedMethod); }
/// <summary> /// Determines whether the given member maps to a server-generated column in the store. /// Requires: InitializeExtentInformation has been called for the extent being persisted. /// </summary> /// <param name="entitySetBase"> Entity set containing member. </param> /// <param name="member"> Member to lookup </param> /// <returns> Whether the member is server generated in some context </returns> internal bool IsServerGen(EntitySetBase entitySetBase, MetadataWorkspace workspace, EdmMember member) { return(SyncContains(entitySetBase, workspace, m_serverGenProperties, member)); }
/// <summary> /// Gets a view corresponding to the specified extent. /// </summary> /// <param name="extent">The extent.</param> /// <returns>The mapping view, or null if the extent is not associated with a mapping view.</returns> public override DbMappingView GetView(EntitySetBase extent) { if (extent == null) { throw new ArgumentNullException("extent"); } var extentName = extent.EntityContainer.Name + "." + extent.Name; if (extentName == "SalesManagementDemoModelStoreContainer.AccountTypes") { return(GetView0()); } if (extentName == "SalesManagementDemoModelStoreContainer.Budget") { return(GetView1()); } if (extentName == "SalesManagementDemoModelStoreContainer.Departments") { return(GetView2()); } if (extentName == "SalesManagementDemoModelStoreContainer.Inventory") { return(GetView3()); } if (extentName == "SalesManagementDemoModelStoreContainer.Order_Details") { return(GetView4()); } if (extentName == "SalesManagementDemoModelStoreContainer.Orders") { return(GetView5()); } if (extentName == "SalesManagementDemoModelStoreContainer.Products") { return(GetView6()); } if (extentName == "SalesManagementDemoModelStoreContainer.Roles") { return(GetView7()); } if (extentName == "SalesManagementDemoModelStoreContainer.Sales") { return(GetView8()); } if (extentName == "SalesManagementDemoModelStoreContainer.User_Details") { return(GetView9()); } if (extentName == "SalesManagementDemoModelStoreContainer.Users") { return(GetView10()); } if (extentName == "SalesManagementDemoEntities.AccountTypes") { return(GetView11()); } if (extentName == "SalesManagementDemoEntities.Budgets") { return(GetView12()); } if (extentName == "SalesManagementDemoEntities.Departments") { return(GetView13()); } if (extentName == "SalesManagementDemoEntities.Inventories") { return(GetView14()); } if (extentName == "SalesManagementDemoEntities.Order_Details") { return(GetView15()); } if (extentName == "SalesManagementDemoEntities.Orders") { return(GetView16()); } if (extentName == "SalesManagementDemoEntities.Products") { return(GetView17()); } if (extentName == "SalesManagementDemoEntities.Roles") { return(GetView18()); } if (extentName == "SalesManagementDemoEntities.Sales") { return(GetView19()); } if (extentName == "SalesManagementDemoEntities.User_Details") { return(GetView20()); } if (extentName == "SalesManagementDemoEntities.Users") { return(GetView21()); } return(null); }
/// <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) { DebugCheck.NotNull(containerMapping); DebugCheck.NotNull(config); DebugCheck.NotNull(entity); DebugCheck.NotNull(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 var args = new InputForComputingCellGroups(containerMapping, config); var result = containerMapping.GetCellgroups(args); success = result.Success; if (!success) { return(null); } var 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 var cellGroups = result.CellGroups.Select(setOfcells => new CellGroup(setOfcells.Select(cell => new Cell(cell)))).ToList(); var cells = result.Cells; var identifiers = result.Identifiers; var viewGenResults = new ViewGenResults(); var tmpLog = EnsureAllCSpaceContainerSetsAreMapped(cells, containerMapping); if (tmpLog.Count > 0) { viewGenResults.AddErrors(tmpLog); Helpers.StringTraceLine(viewGenResults.ErrorsToString()); success = true; //atleast we tried successfully return(viewGenResults); } foreach (var cellGroup in cellGroups) { if (!DoesCellGroupContainEntitySet(cellGroup, entity)) { continue; } ViewGenerator viewGenerator = null; var 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 var 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 ExtentPair(EntitySetBase left, EntitySetBase right) { this.m_left = left; this.m_right = right; }
private CellTreeNode ConvertUnionsToNormalizedLOJs(CellTreeNode rootNode) { // Recursively, transform the subtrees rooted at rootNode's children. for (var i = 0; i < rootNode.Children.Count; i++) { // Method modifies input as well. rootNode.Children[i] = ConvertUnionsToNormalizedLOJs(rootNode.Children[i]); } // We rewrite only LOJs. if (rootNode.OpType != CellTreeOpType.LOJ || rootNode.Children.Count < 2) { return(rootNode); } // Create the resulting LOJ node. var result = new OpCellTreeNode(m_viewgenContext, rootNode.OpType); // Create working collection for the LOJ children. var children = new List <CellTreeNode>(); // If rootNode looks something like ((V0 IJ V1) LOJ V2 LOJ V3), // and it turns out that there are FK associations from V2 or V3 pointing, let's say at V0, // then we want to rewrite the result as (V1 IJ (V0 LOJ V2 LOJ V3)). // If we don't do this, then plan compiler won't have a chance to eliminate LOJ V2 LOJ V3. // Hence, flatten the first child or rootNode if it's IJ, but remember that its parts are driving nodes for the LOJ, // so that we don't accidentally nest them. OpCellTreeNode resultIJDriver = null; HashSet <CellTreeNode> resultIJDriverChildren = null; if (rootNode.Children[0].OpType == CellTreeOpType.IJ) { // Create empty resultIJDriver node and add it as the first child (driving) into the LOJ result. resultIJDriver = new OpCellTreeNode(m_viewgenContext, rootNode.Children[0].OpType); result.Add(resultIJDriver); children.AddRange(rootNode.Children[0].Children); resultIJDriverChildren = new HashSet <CellTreeNode>(rootNode.Children[0].Children); } else { result.Add(rootNode.Children[0]); } // Flatten unions in non-driving nodes: (V0 LOJ (V1 Union V2 Union V3)) -> (V0 LOJ V1 LOJ V2 LOJ V3) foreach (var child in rootNode.Children.Skip(1)) { var opNode = child as OpCellTreeNode; if (opNode != null && opNode.OpType == CellTreeOpType.Union) { children.AddRange(opNode.Children); } else { children.Add(child); } } // A dictionary that maps an extent to the nodes that are from that extent. // We want a ref comparer here. var extentMap = new KeyToListMap <EntitySet, LeafCellTreeNode>(EqualityComparer <EntitySet> .Default); // Note that we skip non-leaf nodes (non-leaf nodes don't have FKs) and attach them directly to the result. foreach (var child in children) { var leaf = child as LeafCellTreeNode; if (leaf != null) { EntitySetBase extent = GetLeafNodeTable(leaf); if (extent != null) { extentMap.Add((EntitySet)extent, leaf); } } else { if (resultIJDriverChildren != null && resultIJDriverChildren.Contains(child)) { resultIJDriver.Add(child); } else { result.Add(child); } } } // We only deal with simple cases - one node per extent, remove the rest from children and attach directly to result. var nonTrivial = extentMap.KeyValuePairs.Where(m => m.Value.Count > 1).ToArray(); foreach (var m in nonTrivial) { extentMap.RemoveKey(m.Key); foreach (var n in m.Value) { if (resultIJDriverChildren != null && resultIJDriverChildren.Contains(n)) { resultIJDriver.Add(n); } else { result.Add(n); } } } Debug.Assert(extentMap.KeyValuePairs.All(m => m.Value.Count == 1), "extentMap must map to single nodes only."); // Walk the extents in extentMap and for each extent build PK -> FK1(PK1), FK2(PK2), ... map // where PK is the primary key of the left extent, and FKn(PKn) is an FK of a right extent that // points to the PK of the left extent and is based on the PK columns of the right extent. // Example: // table tBaseType(Id int, c1 int), PK = (tBaseType.Id) // table tDerivedType1(Id int, c2 int), PK1 = (tDerivedType1.Id), FK1 = (tDerivedType1.Id -> tBaseType.Id) // table tDerivedType2(Id int, c3 int), PK2 = (tDerivedType2.Id), FK2 = (tDerivedType2.Id -> tBaseType.Id) // Will produce: // (tBaseType) -> (tDerivedType1, tDerivedType2) var pkFkMap = new KeyToListMap <EntitySet, EntitySet>(EqualityComparer <EntitySet> .Default); // Also for each extent in extentMap, build another map (extent) -> (LOJ node). // It will be used to construct the nesting in the next step. var extentLOJs = new Dictionary <EntitySet, OpCellTreeNode>(EqualityComparer <EntitySet> .Default); foreach (var extentInfo in extentMap.KeyValuePairs) { var principalExtent = extentInfo.Key; foreach (var fkExtent in GetFKOverPKDependents(principalExtent)) { // Only track fkExtents that are in extentMap. ReadOnlyCollection <LeafCellTreeNode> nodes; if (extentMap.TryGetListForKey(fkExtent, out nodes)) { // Make sure that we are not adding resultIJDriverChildren as FK dependents - we do not want them to get nested. if (resultIJDriverChildren == null || !resultIJDriverChildren.Contains(nodes.Single())) { pkFkMap.Add(principalExtent, fkExtent); } } } var extentLojNode = new OpCellTreeNode(m_viewgenContext, CellTreeOpType.LOJ); extentLojNode.Add(extentInfo.Value.Single()); extentLOJs.Add(principalExtent, extentLojNode); } // Construct LOJ nesting inside extentLOJs based on the information in pkFkMap. // Also, track nested extents using nestedExtents. // Example: // We start with nestedExtents empty extentLOJs as such: // tBaseType -> LOJ(BaseTypeNode) // tDerivedType1 -> LOJ(DerivedType1Node)* // tDerivedType2 -> LOJ(DerivedType2Node)** // Note that * and ** represent object references. So each time something is nested, // we don't clone, but nest the original LOJ. When we get to processing the extent of that LOJ, // we might add other children to that nested LOJ. // As we walk pkFkMap, we end up with this: // tBaseType -> LOJ(BaseTypeNode, LOJ(DerivedType1Node)*, LOJ(DerivedType2Node)**) // tDerivedType1 -> LOJ(DerivedType1Node)* // tDerivedType2 -> LOJ(DerivedType2Node)** // nestedExtens = (tDerivedType1, tDerivedType2) var nestedExtents = new Dictionary <EntitySet, EntitySet>(EqualityComparer <EntitySet> .Default); foreach (var m in pkFkMap.KeyValuePairs) { var principalExtent = m.Key; foreach (var fkExtent in m.Value) { OpCellTreeNode fkExtentLOJ; if (extentLOJs.TryGetValue(fkExtent, out fkExtentLOJ) && // make sure we don't nest twice and we don't create a cycle. !nestedExtents.ContainsKey(fkExtent) && !CheckLOJCycle(fkExtent, principalExtent, nestedExtents)) { extentLOJs[m.Key].Add(fkExtentLOJ); nestedExtents.Add(fkExtent, principalExtent); } } } // Now we need to grab the LOJs that have not been nested and add them to the result. // All LOJs that have been nested must be somewhere inside the LOJs that have not been nested, // so they as well end up in the result as part of the unnested ones. foreach (var m in extentLOJs) { if (!nestedExtents.ContainsKey(m.Key)) { // extentLOJ represents (Vx LOJ Vy LOJ(Vm LOJ Vn)) where Vx is the original node from rootNode.Children or resultIJDriverChildren. var extentLOJ = m.Value; if (resultIJDriverChildren != null && resultIJDriverChildren.Contains(extentLOJ.Children[0])) { resultIJDriver.Add(extentLOJ); } else { result.Add(extentLOJ); } } } return(result.Flatten()); }
/// <summary> /// Gets a view corresponding to the specified extent. /// </summary> /// <param name="extent">The extent.</param> /// <returns>The mapping view, or null if the extent is not associated with a mapping view.</returns> public override DbMappingView GetView(EntitySetBase extent) { if (extent == null) { throw new ArgumentNullException("extent"); } var extentName = extent.EntityContainer.Name + "." + extent.Name; if (extentName == "CodeFirstDatabase.Address") { return(GetView0()); } if (extentName == "CodeFirstDatabase.CustomerAddress") { return(GetView1()); } if (extentName == "CodeFirstDatabase.Customer") { return(GetView2()); } if (extentName == "CodeFirstDatabase.SalesOrderHeader") { return(GetView3()); } if (extentName == "CodeFirstDatabase.SalesOrderDetail") { return(GetView4()); } if (extentName == "CodeFirstDatabase.Product") { return(GetView5()); } if (extentName == "CodeFirstDatabase.ProductCategory") { return(GetView6()); } if (extentName == "CodeFirstDatabase.ProductModel") { return(GetView7()); } if (extentName == "CodeFirstDatabase.ProductModelProductDescription") { return(GetView8()); } if (extentName == "CodeFirstDatabase.ProductDescription") { return(GetView9()); } if (extentName == "AdventureWorksLt2012.Addresses") { return(GetView10()); } if (extentName == "AdventureWorksLt2012.CustomerAddresses") { return(GetView11()); } if (extentName == "AdventureWorksLt2012.Customers") { return(GetView12()); } if (extentName == "AdventureWorksLt2012.SalesOrderHeaders") { return(GetView13()); } if (extentName == "AdventureWorksLt2012.SalesOrderDetails") { return(GetView14()); } if (extentName == "AdventureWorksLt2012.Products") { return(GetView15()); } if (extentName == "AdventureWorksLt2012.ProductCategories") { return(GetView16()); } if (extentName == "AdventureWorksLt2012.ProductModels") { return(GetView17()); } if (extentName == "AdventureWorksLt2012.ProductModelProductDescriptions") { return(GetView18()); } if (extentName == "AdventureWorksLt2012.ProductDescriptions") { return(GetView19()); } if (extentName == "CodeFirstDatabase.vGetAllCategory") { return(GetView20()); } if (extentName == "AdventureWorksLt2012.vGetAllCategories") { return(GetView21()); } if (extentName == "CodeFirstDatabase.vProductAndDescription") { return(GetView22()); } if (extentName == "AdventureWorksLt2012.vProductAndDescriptions") { return(GetView23()); } if (extentName == "CodeFirstDatabase.vProductModelCatalogDescription") { return(GetView24()); } if (extentName == "AdventureWorksLt2012.vProductModelCatalogDescriptions") { return(GetView25()); } return(null); }
private ViewSimplifier(MetadataWorkspace mws, EntitySetBase viewTarget) { this.metadata = mws; this.extent = viewTarget; }
/// <summary> /// Utility method reading value from dictionary within read lock. /// </summary> private T_Value SyncGetValue <T_Key, T_Value>( EntitySetBase entitySetBase, MetadataWorkspace workspace, Dictionary <T_Key, T_Value> dictionary, T_Key key) { return(SyncInitializeEntitySet(entitySetBase, workspace, k => dictionary[k], key)); }
private string GetPrimaryKeyName(Type type) { EntitySetBase es = GetEntitySet(type); return(es.ElementType.KeyMembers[0].Name); }
/// <summary> /// Utility method checking for membership of element in set within read lock. /// </summary> private bool SyncContains <T_Element>( EntitySetBase entitySetBase, MetadataWorkspace workspace, Set <T_Element> set, T_Element element) { return(SyncInitializeEntitySet(entitySetBase, workspace, set.Contains, element)); }
public ScanExpression(string scanString, EntitySetBase target) { _scanString = scanString; _target = target; }
private Type getEntityType(EntitySetBase setBase) { Type setBaseType; if (_entityTypesCache.TryGetValue(setBase, out setBaseType)) { return(setBaseType); } // if it's an entity framework internal table then return null if (isEntityFrameworkInternalTable(setBase)) { return(null); } // Get the part of the model that contains info about the actual CLR types var objectItemCollection = ((ObjectItemCollection)_metadata.GetItemCollection(DataSpace.OSpace)); // Get conceptual model var primitiveTypeCollection = _metadata.GetItems <EntityContainer>(DataSpace.CSpace).Single(); // Get the mapping model var entityPrimitiveMappingCollection = _metadata.GetItems <EntityContainerMapping>(DataSpace.CSSpace).Single(); // Get the entity type from the model and find which entities this set base refers to var oSpace = _metadata.GetItems <EntityType>(DataSpace.OSpace); foreach (var entityType in oSpace) { // Get the entity set that uses this entity type var entitySet = primitiveTypeCollection.EntitySets .SingleOrDefault(s => s.ElementType.Name == entityType.Name); if (entitySet == null) { continue; } // Find the mapping between conceptual and storage model for this entity set var mapping = entityPrimitiveMappingCollection.EntitySetMappings .Single(s => s.EntitySet == entitySet); // Find the storage entity set (table) that the entity is mapped to. // This could be mapped to multiple entities var isRelatedTable = mapping.EntityTypeMappings .SelectMany(typeMapping => typeMapping.Fragments) .Select(fragment => fragment.StoreEntitySet) .Select(set => set.MetadataProperties) .Any(metadataCollection => (string)metadataCollection["Table"].Value == setBase.Table); // is this the table we are looking for? if (isRelatedTable) { var clrType = objectItemCollection.GetClrType(entityType); _entityTypesCache.TryAdd(setBase, clrType); return(clrType); } } // not found! return(null); }