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
- TextParagraphView.cs
- BrowserDefinitionCollection.cs
- EventProvider.cs
- TableRow.cs
- __Error.cs
- UshortList2.cs
- PanelDesigner.cs
- CmsInterop.cs
- SigningDialog.cs
- CodeMemberProperty.cs
- MiniLockedBorderGlyph.cs
- BinaryObjectInfo.cs
- QualificationDataItem.cs
- Scheduling.cs
- ValidatedControlConverter.cs
- OracleFactory.cs
- TreePrinter.cs
- DataGridSortCommandEventArgs.cs
- WorkflowDesignerMessageFilter.cs
- WindowsAuthenticationModule.cs
- OdbcCommandBuilder.cs
- HotCommands.cs
- ExtendedPropertyDescriptor.cs
- ProfileService.cs
- TypefaceMap.cs
- RoleManagerSection.cs
- Metafile.cs
- MimeWriter.cs
- ConnectionPoolManager.cs
- ListMarkerSourceInfo.cs
- ConfigurationStrings.cs
- CqlLexerHelpers.cs
- ModuleConfigurationInfo.cs
- PersonalizablePropertyEntry.cs
- SizeConverter.cs
- KnownIds.cs
- StringValueSerializer.cs
- DecoderNLS.cs
- DataFieldConverter.cs
- SystemWebCachingSectionGroup.cs
- DeviceContext2.cs
- TemplateField.cs
- TextTreeInsertElementUndoUnit.cs
- FontStretch.cs
- SQLDouble.cs
- TreeViewEvent.cs
- ListBindingHelper.cs
- UnionExpr.cs
- CollectionEditor.cs
- RichTextBox.cs
- IntSecurity.cs
- AuthenticationException.cs
- SemanticResolver.cs
- filewebrequest.cs
- WindowsIdentity.cs
- TokenBasedSet.cs
- TextRunProperties.cs
- XPathDocumentIterator.cs
- SharedPersonalizationStateInfo.cs
- ScriptServiceAttribute.cs
- StreamMarshaler.cs
- RegularExpressionValidator.cs
- TextEditorCharacters.cs
- ContentIterators.cs
- BidirectionalDictionary.cs
- Int32EqualityComparer.cs
- BindingCollectionElement.cs
- WpfMemberInvoker.cs
- XPathChildIterator.cs
- PrivateFontCollection.cs
- EdgeModeValidation.cs
- EncodingTable.cs
- _CommandStream.cs
- ToolStripSettings.cs
- StateChangeEvent.cs
- DataSetMappper.cs
- MaskInputRejectedEventArgs.cs
- Columns.cs
- CompositeActivityMarkupSerializer.cs
- XmlSchemaComplexType.cs
- SecurityChannelFactory.cs
- QuaternionRotation3D.cs
- BamlResourceSerializer.cs
- RepeaterItem.cs
- ClientFormsIdentity.cs
- MediaScriptCommandRoutedEventArgs.cs
- SpeakCompletedEventArgs.cs
- GridViewDeleteEventArgs.cs
- TextWriterEngine.cs
- X509SubjectKeyIdentifierClause.cs
- MailBnfHelper.cs
- MessageSecurityOverTcp.cs
- BroadcastEventHelper.cs
- WindowsEditBoxRange.cs
- Module.cs
- Application.cs
- TraceHandlerErrorFormatter.cs
- ContextQuery.cs
- Shape.cs
- GridEntry.cs