Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 2 / 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
- DataGridViewColumnTypePicker.cs
- XmlChildEnumerator.cs
- SqlTriggerContext.cs
- GenericTypeParameterBuilder.cs
- ReferenceSchema.cs
- SecurityTokenResolver.cs
- TextEditorCharacters.cs
- SqlError.cs
- RoutedEventConverter.cs
- XmlQualifiedNameTest.cs
- SystemResourceKey.cs
- MSG.cs
- BasicCellRelation.cs
- ViewPort3D.cs
- UniqueSet.cs
- LocatorGroup.cs
- NetDataContractSerializer.cs
- TreeViewItem.cs
- CharEntityEncoderFallback.cs
- WinCategoryAttribute.cs
- FieldAccessException.cs
- TimeoutValidationAttribute.cs
- XmlAttributeAttribute.cs
- ContractCodeDomInfo.cs
- ActivityInstance.cs
- ClientEventManager.cs
- DotAtomReader.cs
- WebPartActionVerb.cs
- VectorCollection.cs
- SqlRecordBuffer.cs
- GetBrowserTokenRequest.cs
- EdmError.cs
- TextSelectionHighlightLayer.cs
- RecognitionResult.cs
- ClosableStream.cs
- DataColumnPropertyDescriptor.cs
- RSAOAEPKeyExchangeFormatter.cs
- ScriptServiceAttribute.cs
- Camera.cs
- DnsPermission.cs
- TextTreeTextNode.cs
- RelationshipFixer.cs
- ProcessRequestArgs.cs
- CommandEventArgs.cs
- DataGridTable.cs
- SelectionRange.cs
- RawUIStateInputReport.cs
- Rect3DConverter.cs
- IArgumentProvider.cs
- CfgSemanticTag.cs
- DropDownList.cs
- PointIndependentAnimationStorage.cs
- OleDbInfoMessageEvent.cs
- Collection.cs
- Wildcard.cs
- Aggregates.cs
- WmlLabelAdapter.cs
- MetafileHeaderWmf.cs
- EncoderBestFitFallback.cs
- PriorityQueue.cs
- ListViewCommandEventArgs.cs
- PropertyEmitterBase.cs
- BitmapPalettes.cs
- Viewport3DVisual.cs
- XmlProcessingInstruction.cs
- SettingsBindableAttribute.cs
- ImageIndexConverter.cs
- XsdValidatingReader.cs
- FocusTracker.cs
- DataBoundControlHelper.cs
- XmlAttributeCache.cs
- WebPartCancelEventArgs.cs
- OrderByQueryOptionExpression.cs
- Sentence.cs
- DrawingImage.cs
- DrawingVisualDrawingContext.cs
- MissingMethodException.cs
- streamingZipPartStream.cs
- ConfigurationSectionCollection.cs
- WorkflowPrinting.cs
- MethodImplAttribute.cs
- IisTraceListener.cs
- Marshal.cs
- FtpWebRequest.cs
- DataGridViewRowsRemovedEventArgs.cs
- HtmlInputCheckBox.cs
- DirectoryObjectSecurity.cs
- SequentialOutput.cs
- HttpEncoder.cs
- Model3DGroup.cs
- TextParagraphView.cs
- ValueTable.cs
- Crc32Helper.cs
- DocumentApplicationState.cs
- TreeNodeStyle.cs
- RelationshipType.cs
- MarkupCompilePass2.cs
- StringReader.cs
- Table.cs
- PeerTransportSecuritySettings.cs