Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 3 / ClosureBinding.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] //--------------------------------------------------------------------- using System.Collections; using LinqExpression = System.Linq.Expressions.Expression; using CqtExpression = System.Data.Common.CommandTrees.DbExpression; using System.Diagnostics; using System.Collections.Generic; using System.Linq.Expressions; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Globalization; using System.Data.Metadata.Edm; using System.Reflection; using System.Linq; using System.Threading; namespace System.Data.Objects.ELinq { ////// Binding between an object parameter or sub-query and LINQ expression that needs to be /// re-evaluated before executing a query because it is part of the closure. /// /// Invariants: the binding defines either the Parameter or the Query property, not both. /// internal abstract class ClosureBinding { #region Constructors private ClosureBinding(LinqExpression sourceExpression) { _sourceExpression = sourceExpression; } #endregion #region Fields private readonly LinqExpression _sourceExpression; private static readonly string s_parameterPrefix = "p__linq__"; private static long s_parameterNumber; #endregion #region Properties ////// Gets the query produced by this closure expression. Returns null if no /// query is produced. /// internal abstract ObjectQuery Query { get; } ////// Gets the expression produced by this closure expression. Returns null if no /// expression is produced. /// internal abstract LinqExpression Expression { get; } ////// Gets the parameter storing the primitive value produced by this closure expression. /// Returns null if no primitive value is produced. /// internal abstract ObjectParameter Parameter { get; } #endregion #region Methods ////// Evaluates the binding and populates the object parameter value. /// ///true if the entire expression should be re-evaluated (if a sub-expression has changed); /// false otherwise internal abstract bool EvaluateBinding(); internal abstract ClosureBinding CopyToContext(ExpressionConverter context); internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage) { // since ObjectParameters do not allow users to especify 'facets', make // sure that the parameter typeusage is not populated with the provider // dafault facet values if (perspective.TryGetTypeByName(parameter.MappableType.FullName, false, // bIgnoreCase out typeUsage) && TypeSemantics.IsPrimitiveType(typeUsage)) { return true; } typeUsage = null; return false; } ////// requires: expression must not be null /// Attempt to treat the given expression as a supported parameter reference in a closure. /// Succeeds if the pattern of the expression is precisely Member(Constant), and the member /// is of primitive type. /// /// Expression to check. /// Perspective to use to resolve expression type. /// Determines whether Lambda sub-expressions are permitted in this context. /// Closure binding corresponding to the given expression. /// Type usage for the binding. ///true if the given expression can be bound internal static bool TryCreateClosureBinding(LinqExpression expression, ClrPerspective perspective, bool allowLambda, HashSetclosureCandidates, out ClosureBinding binding, out TypeUsage typeUsage) { Debug.Assert(null != expression); if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) && closureCandidates.Contains(expression)) // all nodes below it must qualify also { ObjectParameter parameter = new ObjectParameter(GenerateParameterName(), expression.Type); if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage)) { binding = new ParameterBinding(expression, parameter); // compute the parameter value during translation since we translate directly // before evaluating (in other words, the value of the parameter will not change // between now and the time results are produced) binding.EvaluateBinding(); return true; } // determine if the expression yields an inline ObjectQuery or Expression object result = ExpressionEvaluator.EvaluateExpression(expression); ObjectQuery resultQuery = result as ObjectQuery; if (resultQuery != null) { binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption); return true; } else if (allowLambda && result is LambdaExpression) { binding = new NestedLogicBinding(expression, result, null); return true; } } // doesn't match the pattern binding = null; typeUsage = null; return false; } internal static string GenerateParameterName() { // To avoid collisions with user parameters (the full set is not // known at this time) we plug together an 'unlikely' prefix and // a number. return String.Format(CultureInfo.InvariantCulture, "{0}{1}", s_parameterPrefix, Interlocked.Increment(ref s_parameterNumber)); } #endregion #region Nested types private class NestedLogicBinding : ClosureBinding { private MergeOption? _mergeOption; internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption) : base(sourceExpression) { _nestedLogic = nestedLogic; _mergeOption = mergeOption; } private object _nestedLogic; internal override ClosureBinding CopyToContext(ExpressionConverter context) { return this; } internal override bool EvaluateBinding() { // must recompile entire expression if the sub-expression has changed object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression); if (object.ReferenceEquals(_nestedLogic, currentLogic)) { // The instances are the same; however, if the nested logic is actually // an instance of ObjectQuery, then any mutable properties on the instance // may also have changed. Currently only MergeOption is significant, so it // must be compared here. ObjectQuery query = currentLogic as ObjectQuery; if (query == null) { // The nested logic is not an ObjectQuery; simply return false. return false; } // The only way the merge option can change in a way that affects us // here is if it has been explicitly set using ObjectQuery.MergeOption. MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption; if (!newMergeOption.HasValue && !_mergeOption.HasValue) { // No difference. return false; } if (newMergeOption.HasValue && _mergeOption.HasValue && newMergeOption.Value == _mergeOption.Value) { // No difference. return false; } } return true; } internal override LinqExpression Expression { get { return _nestedLogic as LinqExpression; } } internal override ObjectQuery Query { get { return _nestedLogic as ObjectQuery; } } internal override ObjectParameter Parameter { get { return null; } } } private class ParameterBinding : ClosureBinding { internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter) : base(sourceExpression) { _parameter = parameter; } private ObjectParameter _parameter; internal override ClosureBinding CopyToContext(ExpressionConverter context) { ObjectParameter targetParameter = null; if (context.Parameters != null) { targetParameter = context.Parameters[_parameter.Name]; } return new ParameterBinding(_sourceExpression, targetParameter); } internal override bool EvaluateBinding() { object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression); _parameter.Value = currentValue; return false; } internal override LinqExpression Expression { get { return null; } } internal override ObjectQuery Query { get { return null; } } internal override ObjectParameter Parameter { get { return _parameter; } } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] //--------------------------------------------------------------------- using System.Collections; using LinqExpression = System.Linq.Expressions.Expression; using CqtExpression = System.Data.Common.CommandTrees.DbExpression; using System.Diagnostics; using System.Collections.Generic; using System.Linq.Expressions; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Globalization; using System.Data.Metadata.Edm; using System.Reflection; using System.Linq; using System.Threading; namespace System.Data.Objects.ELinq { ////// Binding between an object parameter or sub-query and LINQ expression that needs to be /// re-evaluated before executing a query because it is part of the closure. /// /// Invariants: the binding defines either the Parameter or the Query property, not both. /// internal abstract class ClosureBinding { #region Constructors private ClosureBinding(LinqExpression sourceExpression) { _sourceExpression = sourceExpression; } #endregion #region Fields private readonly LinqExpression _sourceExpression; private static readonly string s_parameterPrefix = "p__linq__"; private static long s_parameterNumber; #endregion #region Properties ////// Gets the query produced by this closure expression. Returns null if no /// query is produced. /// internal abstract ObjectQuery Query { get; } ////// Gets the expression produced by this closure expression. Returns null if no /// expression is produced. /// internal abstract LinqExpression Expression { get; } ////// Gets the parameter storing the primitive value produced by this closure expression. /// Returns null if no primitive value is produced. /// internal abstract ObjectParameter Parameter { get; } #endregion #region Methods ////// Evaluates the binding and populates the object parameter value. /// ///true if the entire expression should be re-evaluated (if a sub-expression has changed); /// false otherwise internal abstract bool EvaluateBinding(); internal abstract ClosureBinding CopyToContext(ExpressionConverter context); internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage) { // since ObjectParameters do not allow users to especify 'facets', make // sure that the parameter typeusage is not populated with the provider // dafault facet values if (perspective.TryGetTypeByName(parameter.MappableType.FullName, false, // bIgnoreCase out typeUsage) && TypeSemantics.IsPrimitiveType(typeUsage)) { return true; } typeUsage = null; return false; } ////// requires: expression must not be null /// Attempt to treat the given expression as a supported parameter reference in a closure. /// Succeeds if the pattern of the expression is precisely Member(Constant), and the member /// is of primitive type. /// /// Expression to check. /// Perspective to use to resolve expression type. /// Determines whether Lambda sub-expressions are permitted in this context. /// Closure binding corresponding to the given expression. /// Type usage for the binding. ///true if the given expression can be bound internal static bool TryCreateClosureBinding(LinqExpression expression, ClrPerspective perspective, bool allowLambda, HashSetclosureCandidates, out ClosureBinding binding, out TypeUsage typeUsage) { Debug.Assert(null != expression); if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) && closureCandidates.Contains(expression)) // all nodes below it must qualify also { ObjectParameter parameter = new ObjectParameter(GenerateParameterName(), expression.Type); if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage)) { binding = new ParameterBinding(expression, parameter); // compute the parameter value during translation since we translate directly // before evaluating (in other words, the value of the parameter will not change // between now and the time results are produced) binding.EvaluateBinding(); return true; } // determine if the expression yields an inline ObjectQuery or Expression object result = ExpressionEvaluator.EvaluateExpression(expression); ObjectQuery resultQuery = result as ObjectQuery; if (resultQuery != null) { binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption); return true; } else if (allowLambda && result is LambdaExpression) { binding = new NestedLogicBinding(expression, result, null); return true; } } // doesn't match the pattern binding = null; typeUsage = null; return false; } internal static string GenerateParameterName() { // To avoid collisions with user parameters (the full set is not // known at this time) we plug together an 'unlikely' prefix and // a number. return String.Format(CultureInfo.InvariantCulture, "{0}{1}", s_parameterPrefix, Interlocked.Increment(ref s_parameterNumber)); } #endregion #region Nested types private class NestedLogicBinding : ClosureBinding { private MergeOption? _mergeOption; internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption) : base(sourceExpression) { _nestedLogic = nestedLogic; _mergeOption = mergeOption; } private object _nestedLogic; internal override ClosureBinding CopyToContext(ExpressionConverter context) { return this; } internal override bool EvaluateBinding() { // must recompile entire expression if the sub-expression has changed object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression); if (object.ReferenceEquals(_nestedLogic, currentLogic)) { // The instances are the same; however, if the nested logic is actually // an instance of ObjectQuery, then any mutable properties on the instance // may also have changed. Currently only MergeOption is significant, so it // must be compared here. ObjectQuery query = currentLogic as ObjectQuery; if (query == null) { // The nested logic is not an ObjectQuery; simply return false. return false; } // The only way the merge option can change in a way that affects us // here is if it has been explicitly set using ObjectQuery.MergeOption. MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption; if (!newMergeOption.HasValue && !_mergeOption.HasValue) { // No difference. return false; } if (newMergeOption.HasValue && _mergeOption.HasValue && newMergeOption.Value == _mergeOption.Value) { // No difference. return false; } } return true; } internal override LinqExpression Expression { get { return _nestedLogic as LinqExpression; } } internal override ObjectQuery Query { get { return _nestedLogic as ObjectQuery; } } internal override ObjectParameter Parameter { get { return null; } } } private class ParameterBinding : ClosureBinding { internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter) : base(sourceExpression) { _parameter = parameter; } private ObjectParameter _parameter; internal override ClosureBinding CopyToContext(ExpressionConverter context) { ObjectParameter targetParameter = null; if (context.Parameters != null) { targetParameter = context.Parameters[_parameter.Name]; } return new ParameterBinding(_sourceExpression, targetParameter); } internal override bool EvaluateBinding() { object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression); _parameter.Value = currentValue; return false; } internal override LinqExpression Expression { get { return null; } } internal override ObjectQuery Query { get { return null; } } internal override ObjectParameter Parameter { get { return _parameter; } } } #endregion } } // 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
- ViewGenerator.cs
- ImageAnimator.cs
- SpStreamWrapper.cs
- ObfuscationAttribute.cs
- QuaternionAnimation.cs
- WebPartsSection.cs
- CodeTypeMemberCollection.cs
- BaseDataListDesigner.cs
- MetadataArtifactLoaderComposite.cs
- BulletedList.cs
- SecurityManager.cs
- StorageEntityTypeMapping.cs
- pingexception.cs
- ModelFunction.cs
- DataMisalignedException.cs
- FrameworkTextComposition.cs
- DataRowView.cs
- ViewValidator.cs
- XmlTextReaderImpl.cs
- RequestUriProcessor.cs
- ExpressionConverter.cs
- XmlQueryCardinality.cs
- XXXOnTypeBuilderInstantiation.cs
- BlurBitmapEffect.cs
- PackageStore.cs
- MsmqReceiveParameters.cs
- OpenTypeCommon.cs
- AppDomain.cs
- UserControl.cs
- ClusterRegistryConfigurationProvider.cs
- CommonObjectSecurity.cs
- MailMessageEventArgs.cs
- DynamicPropertyHolder.cs
- TableCell.cs
- SafeFileMappingHandle.cs
- PeerCollaborationPermission.cs
- TabPage.cs
- TextureBrush.cs
- TouchDevice.cs
- CompilationRelaxations.cs
- HuffmanTree.cs
- Compiler.cs
- EncryptedKeyIdentifierClause.cs
- InternalCache.cs
- CodeCatchClauseCollection.cs
- LassoHelper.cs
- SeekStoryboard.cs
- SmiRequestExecutor.cs
- PasswordBoxAutomationPeer.cs
- Task.cs
- StrokeNodeOperations.cs
- ExtentCqlBlock.cs
- TextEditorMouse.cs
- OptionUsage.cs
- SettingsProviderCollection.cs
- ExceptionValidationRule.cs
- GridViewHeaderRowPresenterAutomationPeer.cs
- DetailsViewModeEventArgs.cs
- IPPacketInformation.cs
- UserPersonalizationStateInfo.cs
- initElementDictionary.cs
- SystemIPv4InterfaceProperties.cs
- InputBuffer.cs
- SafeSecurityHandles.cs
- StandardToolWindows.cs
- MailAddressCollection.cs
- ComponentResourceKeyConverter.cs
- AuthorizationContext.cs
- RedirectionProxy.cs
- TcpHostedTransportConfiguration.cs
- Oid.cs
- TransportSecurityHelpers.cs
- TextElementCollection.cs
- ListBoxItemWrapperAutomationPeer.cs
- _ShellExpression.cs
- ContractMethodParameterInfo.cs
- XmlElementAttribute.cs
- securitymgrsite.cs
- DataServices.cs
- BamlRecords.cs
- StringPropertyBuilder.cs
- OptimizedTemplateContent.cs
- EdmType.cs
- BindingOperations.cs
- CallContext.cs
- FloaterParagraph.cs
- DebugInfoGenerator.cs
- Point3DCollection.cs
- SignedXmlDebugLog.cs
- SynchronizedReadOnlyCollection.cs
- ComponentEvent.cs
- ApplicationManager.cs
- DrawingContextDrawingContextWalker.cs
- Table.cs
- ListViewSelectEventArgs.cs
- X509ThumbprintKeyIdentifierClause.cs
- SortDescription.cs
- OperatingSystem.cs
- TypeDescriptionProvider.cs
- Dump.cs