Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Mapping / ViewValidator.cs / 1305376 / ViewValidator.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Globalization; using System.Data.Common.CommandTrees; using System.Collections.Generic; using System.Diagnostics; using System.Data.Entity; using System.Linq; using System.Data.Common.Utils; namespace System.Data.Mapping { ////// Verifies that only legal expressions exist in a user-defined query mapping view. /// /// - ViewExpr = (see ViewExpressionValidator) /// Project(Projection, ViewExpr) | /// Project(Value, ViewExpr) | /// Filter(ViewExpr, ViewExpr) | /// Join(ViewExpr, ViewExpr, ViewExpr) | /// UnionAll(ViewExpr, ViewExpr) | /// Scan(S-Space EntitySet) /// Constant | /// Property{StructuralProperty}(ViewExpr) | /// Null | /// VariableReference | /// Cast(ViewExpr) | /// Case([Predicate, ViewExpr]*, ViewExpr) | /// Comparison(ViewExpr, ViewExpr) | /// Not(ViewExpr) | /// And(ViewExpr, ViewExpr) | /// Or(ViewExpr, ViewExpr) | /// IsNull(ViewExpr) /// - Projection = (see ViewExpressionValidator.Visit(DbProjectExpression) /// NewInstance{TargetEntity}(ViewExpr*) | /// NewInstance{Row}(ViewExpr*) /// internal static class ViewValidator { ////// Determines whether the given view is valid. /// /// Query view to validate. /// Store item collection. /// Mapping in which view is declared. ///Errors in view definition. internal static IEnumerableValidateQueryView(DbQueryCommandTree view, StorageSetMapping setMapping, EntityTypeBase elementType, bool includeSubtypes) { ViewExpressionValidator validator = new ViewExpressionValidator(setMapping, elementType, includeSubtypes); validator.VisitExpression(view.Query); if (validator.Errors.Count() == 0) { //For AssociationSet views, we have to check for a specific pattern of errors where //the Ref expression passed into the construcor might use an EntitySet that is different from //the EntitySet defined in the CSDL. if (setMapping.Set.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { AssociationSetViewValidator refValidator = new AssociationSetViewValidator(setMapping); refValidator.VisitExpression(view.Query); return refValidator.Errors; } } return validator.Errors; } private sealed class ViewExpressionValidator : BasicExpressionVisitor { private readonly StorageSetMapping _setMapping; private readonly List _errors; private readonly EntityTypeBase _elementType; private readonly bool _includeSubtypes; private EdmItemCollection EdmItemCollection { get { return _setMapping.EntityContainerMapping.StorageMappingItemCollection.EdmItemCollection; } } internal ViewExpressionValidator(StorageSetMapping setMapping, EntityTypeBase elementType, bool includeSubtypes) { Debug.Assert(null != setMapping); Debug.Assert(null != elementType); _setMapping = setMapping; _elementType = elementType; _includeSubtypes = includeSubtypes; _errors = new List (); } internal IEnumerable Errors { get { return _errors; } } public override void VisitExpression(DbExpression expression) { if (null != expression) { ValidateExpressionKind(expression.ExpressionKind); } base.VisitExpression(expression); } private void ValidateExpressionKind(DbExpressionKind expressionKind) { switch (expressionKind) { // Supported expression kinds case DbExpressionKind.Constant: case DbExpressionKind.Property: case DbExpressionKind.Null: case DbExpressionKind.VariableReference: case DbExpressionKind.Cast: case DbExpressionKind.Case: case DbExpressionKind.Not: case DbExpressionKind.Or: case DbExpressionKind.And: case DbExpressionKind.IsNull: case DbExpressionKind.Equals: case DbExpressionKind.NotEquals: case DbExpressionKind.LessThan: case DbExpressionKind.LessThanOrEquals: case DbExpressionKind.GreaterThan: case DbExpressionKind.GreaterThanOrEquals: case DbExpressionKind.Project: case DbExpressionKind.NewInstance: case DbExpressionKind.Filter: case DbExpressionKind.Ref: case DbExpressionKind.UnionAll: case DbExpressionKind.Scan: case DbExpressionKind.FullOuterJoin: case DbExpressionKind.LeftOuterJoin: case DbExpressionKind.InnerJoin: case DbExpressionKind.EntityRef: break; default: string elementString = (_includeSubtypes) ? "IsTypeOf(" + _elementType.ToString() + ")" : _elementType.ToString(); _errors.Add(new EdmSchemaError(System.Data.Entity.Strings.Mapping_UnsupportedExpressionKind_QueryView_2( _setMapping.Set.Name, elementString, expressionKind), (int)StorageMappingErrorCode.MappingUnsupportedExpressionKindQueryView, EdmSchemaErrorSeverity.Error, _setMapping.EntityContainerMapping.SourceLocation, _setMapping.StartLineNumber, _setMapping.StartLinePosition)); break; } } public override void Visit(DbPropertyExpression expression) { base.Visit(expression); if (expression.Property.BuiltInTypeKind != BuiltInTypeKind.EdmProperty) { _errors.Add(new EdmSchemaError(System.Data.Entity.Strings.Mapping_UnsupportedPropertyKind_QueryView_3( _setMapping.Set.Name, expression.Property.Name, expression.Property.BuiltInTypeKind), (int)StorageMappingErrorCode.MappingUnsupportedPropertyKindQueryView, EdmSchemaErrorSeverity.Error, _setMapping.EntityContainerMapping.SourceLocation, _setMapping.StartLineNumber, _setMapping.StartLinePosition)); } } public override void Visit(DbNewInstanceExpression expression) { base.Visit(expression); EdmType type = expression.ResultType.EdmType; if (type.BuiltInTypeKind != BuiltInTypeKind.RowType) { // restrict initialization of non-row types to the target of the view or complex types // in the target if (!(type == _elementType || (_includeSubtypes && _elementType.IsAssignableFrom(type))) && !(type.BuiltInTypeKind == BuiltInTypeKind.ComplexType && GetComplexTypes().Contains((ComplexType)type))) { _errors.Add(new EdmSchemaError(System.Data.Entity.Strings.Mapping_UnsupportedInitialization_QueryView_2( _setMapping.Set.Name, type.FullName), (int)StorageMappingErrorCode.MappingUnsupportedInitializationQueryView, EdmSchemaErrorSeverity.Error, _setMapping.EntityContainerMapping.SourceLocation, _setMapping.StartLineNumber, _setMapping.StartLinePosition)); } } } /// /// Retrieves all complex types that can be constructed as part of the view. /// private IEnumerableGetComplexTypes() { // Retrieve all top-level properties of entity types constructed in the view. IEnumerable properties = GetEntityTypes().SelectMany(entityType => entityType.Properties).Distinct(); return GetComplexTypes(properties); } /// /// Recursively identify complex types. /// private IEnumerableGetComplexTypes(IEnumerable properties) { // foreach (ComplexType complexType in properties.Select(p => p.TypeUsage.EdmType).OfType ()) { yield return complexType; foreach (ComplexType nestedComplexType in GetComplexTypes(complexType.Properties)) { yield return nestedComplexType; } } } /// /// Gets all entity types in scope for this view. /// private IEnumerableGetEntityTypes() { if (_includeSubtypes) { // Return all entity types in the hierarchy for OfType or 'complete' views. return MetadataHelper.GetTypeAndSubtypesOf(_elementType, this.EdmItemCollection, true).OfType (); } else if (_elementType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { // Yield single entity type for OfType(only ) views. return Enumerable.Repeat((EntityType)_elementType, 1); } else { // For association set views, there are no entity types involved. return Enumerable.Empty (); } } public override void Visit(DbScanExpression expression) { base.Visit(expression); Debug.Assert(null != expression.Target); // verify scan target is in S-space EntitySetBase target = expression.Target; EntityContainer targetContainer = target.EntityContainer; Debug.Assert(null != target.EntityContainer); if ((targetContainer.DataSpace != DataSpace.SSpace)) { _errors.Add(new EdmSchemaError(System.Data.Entity.Strings.Mapping_UnsupportedScanTarget_QueryView_2( _setMapping.Set.Name, target.Name), (int)StorageMappingErrorCode.MappingUnsupportedScanTargetQueryView, EdmSchemaErrorSeverity.Error, _setMapping.EntityContainerMapping.SourceLocation, _setMapping.StartLineNumber, _setMapping.StartLinePosition)); } } } /// /// The visitor validates that the QueryView for an AssociationSet uses the same EntitySets when /// creating the ends that were used in CSDL. Since the Query View is already validated, we can expect to /// see only a very restricted set of expressions in the tree. /// private class AssociationSetViewValidator : DbExpressionVisitor{ private readonly Stack > variableScopes = new Stack >(); private StorageSetMapping _setMapping; private List _errors = new List (); internal AssociationSetViewValidator(StorageSetMapping setMapping) : base() { Debug.Assert(setMapping != null); _setMapping = setMapping; } internal List Errors { get { return _errors; } } internal DbExpressionEntitySetInfo VisitExpression(DbExpression expression) { return expression.Accept(this); } private DbExpressionEntitySetInfo VisitExpressionBinding(DbExpressionBinding binding) { DbExpressionBinding result = binding; if (binding != null) { return this.VisitExpression(binding.Expression); } return null; } private void VisitExpressionBindingEnterScope(DbExpressionBinding binding) { DbExpressionEntitySetInfo info = this.VisitExpressionBinding(binding); this.variableScopes.Push(new KeyValuePair (binding.VariableName, info)); } private void VisitExpressionBindingExitScope() { this.variableScopes.Pop(); } //Verifies that the Sets we got from visiting the tree( under AssociationType constructor) match the ones //defined in CSDL private void ValidateEntitySetsMappedForAssociationSetMapping(DbExpressionStructuralTypeEntitySetInfo setInfos) { AssociationSet associationSet = _setMapping.Set as AssociationSet; int i = 0; //While we should be able to find the EntitySets in all cases, since this is a user specified //query view, it is better to be defensive since we might have missed some path up the tree //while computing the sets if (setInfos.SetInfos.All(it => ((it.Value != null) && (it.Value is DbExpressionSimpleTypeEntitySetInfo))) && setInfos.SetInfos.Count() == 2) { foreach (DbExpressionSimpleTypeEntitySetInfo setInfo in setInfos.SetInfos.Select(it => it.Value)) { AssociationSetEnd setEnd = associationSet.AssociationSetEnds[i]; EntitySet declaredSet = setEnd.EntitySet; if (!declaredSet.Equals(setInfo.EntitySet)) { _errors.Add(new EdmSchemaError(System.Data.Entity.Strings.Mapping_EntitySetMismatchOnAssociationSetEnd_QueryView_4( setInfo.EntitySet.Name, declaredSet.Name, setEnd.Name, _setMapping.Set.Name), (int)StorageMappingErrorCode.MappingUnsupportedInitializationQueryView, EdmSchemaErrorSeverity.Error, _setMapping.EntityContainerMapping.SourceLocation, _setMapping.StartLineNumber, _setMapping.StartLinePosition)); } i++; } } } #region DbExpressionVisitor Members public override DbExpressionEntitySetInfo Visit(DbExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbVariableReferenceExpression expression) { return this.variableScopes.Where(it => (it.Key == expression.VariableName)).Select(it => it.Value).FirstOrDefault(); } public override DbExpressionEntitySetInfo Visit(DbPropertyExpression expression) { DbExpressionStructuralTypeEntitySetInfo setInfos = VisitExpression(expression.Instance) as DbExpressionStructuralTypeEntitySetInfo; if (setInfos != null) { return setInfos.GetEntitySetInfoForMember(expression.Property.Name); } return null; } public override DbExpressionEntitySetInfo Visit(DbProjectExpression expression) { this.VisitExpressionBindingEnterScope(expression.Input); DbExpressionEntitySetInfo setInfo = VisitExpression(expression.Projection); this.VisitExpressionBindingExitScope(); return setInfo; } public override DbExpressionEntitySetInfo Visit(DbNewInstanceExpression expression) { DbExpressionMemberCollectionEntitySetInfo argumentSetInfos = VisitExpressionList(expression.Arguments); StructuralType structuralType = (expression.ResultType.EdmType as StructuralType); if (argumentSetInfos != null && structuralType != null) { DbExpressionStructuralTypeEntitySetInfo structuralTypeSetInfos = new DbExpressionStructuralTypeEntitySetInfo(); int i = 0; foreach (DbExpressionEntitySetInfo info in argumentSetInfos.entitySetInfos) { structuralTypeSetInfos.Add(structuralType.Members[i].Name, info); i++; } //Since we already validated the query view, the only association type that //can be constructed is the type for the set we are validating the mapping for. if (expression.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.AssociationType) { ValidateEntitySetsMappedForAssociationSetMapping(structuralTypeSetInfos); } return structuralTypeSetInfos; } return null; } private DbExpressionMemberCollectionEntitySetInfo VisitExpressionList(IList list) { return new DbExpressionMemberCollectionEntitySetInfo(list.Select(it => (VisitExpression(it)))); } public override DbExpressionEntitySetInfo Visit(DbRefExpression expression) { return new DbExpressionSimpleTypeEntitySetInfo(expression.EntitySet); } public override DbExpressionEntitySetInfo Visit(DbComparisonExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbLikeExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbLimitExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbIsNullExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbArithmeticExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbAndExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbOrExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbNotExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbDistinctExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbElementExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbIsEmptyExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbUnionAllExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbIntersectExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbExceptExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbTreatExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbIsOfExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbCastExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbCaseExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbOfTypeExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbRelationshipNavigationExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbDerefExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbRefKeyExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbEntityRefExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbScanExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbFilterExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbConstantExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbNullExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbCrossJoinExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbJoinExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbParameterReferenceExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbFunctionExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbLambdaExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbApplyExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbGroupByExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbSkipExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbSortExpression expression) { return null; } public override DbExpressionEntitySetInfo Visit(DbQuantifierExpression expression) { return null; } #endregion } internal class DbExpressionEntitySetInfo { } private class DbExpressionSimpleTypeEntitySetInfo : DbExpressionEntitySetInfo { private EntitySet m_entitySet; internal EntitySet EntitySet { get { return m_entitySet; } } internal DbExpressionSimpleTypeEntitySetInfo(EntitySet entitySet) { m_entitySet = entitySet; } } private class DbExpressionStructuralTypeEntitySetInfo : DbExpressionEntitySetInfo { private Dictionary m_entitySetInfos; internal DbExpressionStructuralTypeEntitySetInfo() { m_entitySetInfos = new Dictionary (); } internal void Add(string key, DbExpressionEntitySetInfo value) { m_entitySetInfos.Add(key, value); } internal IEnumerable > SetInfos { get { return m_entitySetInfos; } } internal DbExpressionEntitySetInfo GetEntitySetInfoForMember(string memberName) { return m_entitySetInfos[memberName]; } } private class DbExpressionMemberCollectionEntitySetInfo : DbExpressionEntitySetInfo { private IEnumerable m_entitySets; internal DbExpressionMemberCollectionEntitySetInfo(IEnumerable entitySetInfos) { m_entitySets = entitySetInfos; } internal IEnumerable entitySetInfos { get { return m_entitySets; } } } } } // 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
- DropShadowEffect.cs
- Int32Storage.cs
- ProfileBuildProvider.cs
- EntityDataSourceChangingEventArgs.cs
- FontStretches.cs
- BaseTypeViewSchema.cs
- SystemKeyConverter.cs
- EventDescriptorCollection.cs
- AttributeUsageAttribute.cs
- BindingMAnagerBase.cs
- ListViewCommandEventArgs.cs
- DescendantQuery.cs
- ZeroOpNode.cs
- DynamicPropertyHolder.cs
- XAMLParseException.cs
- MultipartIdentifier.cs
- BaseDataList.cs
- HttpInputStream.cs
- Inline.cs
- ExtensionFile.cs
- DataGridViewCellStyleBuilderDialog.cs
- ListViewItem.cs
- WizardPanelChangingEventArgs.cs
- BCLDebug.cs
- PlatformNotSupportedException.cs
- GeneralTransform3D.cs
- PixelFormats.cs
- OrderablePartitioner.cs
- TextCompositionEventArgs.cs
- DecimalAnimation.cs
- SqlTypesSchemaImporter.cs
- MimeBasePart.cs
- DataGridViewTopRowAccessibleObject.cs
- SwitchExpression.cs
- TimelineCollection.cs
- MetadataWorkspace.cs
- InternalCache.cs
- SQLRoleProvider.cs
- CheckBoxField.cs
- DbConnectionPoolGroupProviderInfo.cs
- TextEditorTables.cs
- GroupBoxAutomationPeer.cs
- BitmapCodecInfo.cs
- XmlSchemaSequence.cs
- updateconfighost.cs
- SelectionProviderWrapper.cs
- Win32KeyboardDevice.cs
- PreProcessInputEventArgs.cs
- KeyManager.cs
- PageClientProxyGenerator.cs
- BindingOperations.cs
- Mapping.cs
- EdmComplexTypeAttribute.cs
- MonitorWrapper.cs
- DbModificationClause.cs
- XmlElementAttribute.cs
- JournalEntry.cs
- TextFormatter.cs
- InfiniteIntConverter.cs
- TextPattern.cs
- CmsUtils.cs
- CollectionExtensions.cs
- ListViewDesigner.cs
- MappingMetadataHelper.cs
- UDPClient.cs
- OrthographicCamera.cs
- SqlRemoveConstantOrderBy.cs
- EntityProviderServices.cs
- ProtectedConfiguration.cs
- DispatcherHookEventArgs.cs
- ObjectListShowCommandsEventArgs.cs
- WindowsRichEditRange.cs
- BitmapPalettes.cs
- BinarySerializer.cs
- TableLayoutPanel.cs
- SharedPerformanceCounter.cs
- XPathBinder.cs
- SrgsElement.cs
- InputLanguageManager.cs
- HwndSubclass.cs
- XmlArrayItemAttribute.cs
- SingleObjectCollection.cs
- BitmapFrame.cs
- JapaneseCalendar.cs
- ToggleProviderWrapper.cs
- SizeConverter.cs
- SingleQueryOperator.cs
- XmlSchemaType.cs
- DurableDispatcherAddressingFault.cs
- RepeaterCommandEventArgs.cs
- Itemizer.cs
- MarshalByRefObject.cs
- PartManifestEntry.cs
- DataGridViewComboBoxEditingControl.cs
- Vector3DAnimationUsingKeyFrames.cs
- KeyNotFoundException.cs
- PreviewPrintController.cs
- PaginationProgressEventArgs.cs
- MenuBindingsEditorForm.cs
- PartialClassGenerationTaskInternal.cs