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 IEnumerable ValidateQueryView(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 IEnumerable GetComplexTypes()
{
// 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 IEnumerable GetComplexTypes(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 IEnumerable GetEntityTypes()
{
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
- DataGridViewBindingCompleteEventArgs.cs
- Size3DValueSerializer.cs
- ComplusEndpointConfigContainer.cs
- XsltContext.cs
- ParameterElement.cs
- SimpleWebHandlerParser.cs
- SettingsPropertyValue.cs
- QuerySelectOp.cs
- TextTreeText.cs
- ImageSource.cs
- MemoryMappedView.cs
- IgnoreFileBuildProvider.cs
- ImageFormatConverter.cs
- TextChange.cs
- ItemAutomationPeer.cs
- MonthChangedEventArgs.cs
- SByteConverter.cs
- ColorPalette.cs
- SortableBindingList.cs
- XamlReader.cs
- DataGridViewComboBoxColumnDesigner.cs
- CompoundFileDeflateTransform.cs
- PhysicalOps.cs
- QueryOptionExpression.cs
- StylusPointCollection.cs
- RsaSecurityKey.cs
- CodeAccessSecurityEngine.cs
- NetworkInformationException.cs
- _HeaderInfo.cs
- DBDataPermission.cs
- TraceSwitch.cs
- IConvertible.cs
- TextEditorTyping.cs
- SerialPinChanges.cs
- CodeCatchClauseCollection.cs
- Debug.cs
- ObjectViewFactory.cs
- MouseButton.cs
- DataSpaceManager.cs
- IisTraceListener.cs
- BitmapCodecInfoInternal.cs
- SQLGuid.cs
- FormsAuthentication.cs
- TreeIterator.cs
- SizeAnimationClockResource.cs
- TableLayoutPanel.cs
- ImageConverter.cs
- RelOps.cs
- HttpEncoderUtility.cs
- CreateUserWizardDesigner.cs
- EventLogSession.cs
- BrowserCapabilitiesFactoryBase.cs
- ListViewDeletedEventArgs.cs
- wmiutil.cs
- TypeDelegator.cs
- Attachment.cs
- KeyNotFoundException.cs
- ModuleElement.cs
- AssemblySettingAttributes.cs
- DataGridTableStyleMappingNameEditor.cs
- ModuleBuilder.cs
- RegexNode.cs
- CommonProperties.cs
- ButtonChrome.cs
- OdbcParameterCollection.cs
- ServiceThrottle.cs
- ConstraintEnumerator.cs
- BamlBinaryReader.cs
- SemaphoreFullException.cs
- UpdateTranslator.cs
- DataColumn.cs
- WindowsGraphicsCacheManager.cs
- TreeNode.cs
- NavigateUrlConverter.cs
- SqlUtil.cs
- DbConvert.cs
- MediaElementAutomationPeer.cs
- Span.cs
- Preprocessor.cs
- HtmlHead.cs
- TrimSurroundingWhitespaceAttribute.cs
- x509store.cs
- MemoryRecordBuffer.cs
- XmlSchemaComplexType.cs
- Transform.cs
- ResolveDuplexAsyncResult.cs
- MarkedHighlightComponent.cs
- SRDisplayNameAttribute.cs
- Knowncolors.cs
- XmlNodeList.cs
- XsltLibrary.cs
- DynamicDocumentPaginator.cs
- unsafenativemethodsother.cs
- QilValidationVisitor.cs
- FileLoadException.cs
- Missing.cs
- CompilerLocalReference.cs
- Collection.cs
- WmfPlaceableFileHeader.cs
- StoragePropertyMapping.cs