Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 1 / 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
- ZipIOExtraField.cs
- SubstitutionDesigner.cs
- IFormattable.cs
- ConfigurationStrings.cs
- SqlBooleanMismatchVisitor.cs
- DataGridPreparingCellForEditEventArgs.cs
- ISessionStateStore.cs
- BrowserTree.cs
- RC2.cs
- BeginStoryboard.cs
- DateTimeOffsetAdapter.cs
- MailWebEventProvider.cs
- ConfigsHelper.cs
- WsatEtwTraceListener.cs
- WebPartEditVerb.cs
- CodeAttributeDeclarationCollection.cs
- webproxy.cs
- ValidatorUtils.cs
- XmlEntityReference.cs
- InternalConfigEventArgs.cs
- ViewPort3D.cs
- ListItem.cs
- Positioning.cs
- DependencyPropertyAttribute.cs
- XmlSerializationWriter.cs
- StringPropertyBuilder.cs
- MailWebEventProvider.cs
- TableLayoutSettings.cs
- PersonalizationStateInfo.cs
- CodeGotoStatement.cs
- Splitter.cs
- ObservableDictionary.cs
- ProxyElement.cs
- HyperLinkDataBindingHandler.cs
- CatalogZoneAutoFormat.cs
- ValidationEventArgs.cs
- FormsIdentity.cs
- IisTraceListener.cs
- PathParser.cs
- HelpOperationInvoker.cs
- UnsafeNativeMethods.cs
- StateManagedCollection.cs
- TextEditorDragDrop.cs
- PropertyGridEditorPart.cs
- TextTreeFixupNode.cs
- ImageConverter.cs
- DataGridViewRowConverter.cs
- SamlAuthenticationStatement.cs
- XamlDebuggerXmlReader.cs
- SoapMessage.cs
- DataGridViewDataErrorEventArgs.cs
- SQLBoolean.cs
- StreamReader.cs
- DbProviderFactory.cs
- AnnotationStore.cs
- AsyncDataRequest.cs
- ImageAnimator.cs
- _NetworkingPerfCounters.cs
- TableFieldsEditor.cs
- CachingHintValidation.cs
- SizeLimitedCache.cs
- MulticastIPAddressInformationCollection.cs
- XsdValidatingReader.cs
- DataControlLinkButton.cs
- DataGridViewCellFormattingEventArgs.cs
- WebBrowserHelper.cs
- FunctionMappingTranslator.cs
- DrawingBrush.cs
- PkcsUtils.cs
- ThousandthOfEmRealDoubles.cs
- XmlCharCheckingReader.cs
- ProgramNode.cs
- BitmapData.cs
- XPathNodeList.cs
- WorkItem.cs
- wgx_commands.cs
- Match.cs
- ConfigsHelper.cs
- ExpressionPrefixAttribute.cs
- PointHitTestParameters.cs
- InvalidEnumArgumentException.cs
- BufferModesCollection.cs
- StorageBasedPackageProperties.cs
- SecurityUniqueId.cs
- TrackBar.cs
- DocumentGridContextMenu.cs
- DispatcherExceptionEventArgs.cs
- InputLanguageSource.cs
- SubMenuStyleCollectionEditor.cs
- ValueCollectionParameterReader.cs
- NetCodeGroup.cs
- EntityCodeGenerator.cs
- StorageAssociationSetMapping.cs
- PromptStyle.cs
- SamlSerializer.cs
- TdsEnums.cs
- ListViewAutomationPeer.cs
- KnownIds.cs
- InfoCardAsymmetricCrypto.cs
- UnicodeEncoding.cs