Code:
/ 4.0 / 4.0 / 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. //---------------------------------------------------------------------- // // 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
- DataGridViewComboBoxColumn.cs
- EffectiveValueEntry.cs
- SessionStateModule.cs
- HexParser.cs
- GPRECTF.cs
- BoundingRectTracker.cs
- GridViewUpdateEventArgs.cs
- WebPartsPersonalizationAuthorization.cs
- TrueReadOnlyCollection.cs
- ExceptionUtil.cs
- SecurityCookieModeValidator.cs
- DependencyPropertyConverter.cs
- EmulateRecognizeCompletedEventArgs.cs
- _ConnectOverlappedAsyncResult.cs
- DataGridViewRowCollection.cs
- SiteMapSection.cs
- DiagnosticsConfiguration.cs
- AudioException.cs
- cookie.cs
- SqlConnectionString.cs
- RemotingService.cs
- PagePropertiesChangingEventArgs.cs
- WebBrowserProgressChangedEventHandler.cs
- ScriptingSectionGroup.cs
- RangeValueProviderWrapper.cs
- SqlComparer.cs
- AstTree.cs
- AnchoredBlock.cs
- CodeNamespaceImport.cs
- SpotLight.cs
- FontSizeConverter.cs
- NotFiniteNumberException.cs
- NodeLabelEditEvent.cs
- MissingManifestResourceException.cs
- PropertyExpression.cs
- CompositeKey.cs
- MimeTypePropertyAttribute.cs
- HttpFormatExtensions.cs
- SystemIcmpV4Statistics.cs
- ImageInfo.cs
- ViewUtilities.cs
- Control.cs
- RequestCacheEntry.cs
- HScrollBar.cs
- BlobPersonalizationState.cs
- DependencyPropertyDescriptor.cs
- DataGridViewSelectedColumnCollection.cs
- DesignerDataParameter.cs
- CmsUtils.cs
- OneOfScalarConst.cs
- SerializationInfoEnumerator.cs
- DecoderExceptionFallback.cs
- SecuritySessionClientSettings.cs
- DetailsViewRow.cs
- ProcessThreadCollection.cs
- AliasGenerator.cs
- ToolBarButtonClickEvent.cs
- BitStack.cs
- XmlSchemaImport.cs
- WindowClosedEventArgs.cs
- ACL.cs
- WmpBitmapEncoder.cs
- WmlControlAdapter.cs
- COM2TypeInfoProcessor.cs
- WindowsGrip.cs
- OciEnlistContext.cs
- SqlComparer.cs
- WindowsImpersonationContext.cs
- UniqueIdentifierService.cs
- Binding.cs
- Deflater.cs
- ArcSegment.cs
- LiteralControl.cs
- SqlDataSourceSelectingEventArgs.cs
- FormViewRow.cs
- xmlglyphRunInfo.cs
- HwndStylusInputProvider.cs
- Thickness.cs
- DataGridBoundColumn.cs
- HotSpotCollection.cs
- UInt64Storage.cs
- IApplicationTrustManager.cs
- WebPartsPersonalizationAuthorization.cs
- TextEditor.cs
- IPHostEntry.cs
- MoveSizeWinEventHandler.cs
- WSTrustFeb2005.cs
- VerificationAttribute.cs
- VariantWrapper.cs
- WorkflowTimerService.cs
- ProvideValueServiceProvider.cs
- DBSchemaRow.cs
- Stylesheet.cs
- IfAction.cs
- XmlEnumAttribute.cs
- ProgressBarHighlightConverter.cs
- HttpResponseHeader.cs
- IResourceProvider.cs
- ZoneButton.cs
- Line.cs