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, HashSet closureCandidates, 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, HashSet closureCandidates, 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
- GeometryGroup.cs
- EntityTypeBase.cs
- ListView.cs
- RootBrowserWindow.cs
- WebPartZone.cs
- InternalMappingException.cs
- RadioButton.cs
- SharedPerformanceCounter.cs
- WpfKnownTypeInvoker.cs
- BufferedGraphicsManager.cs
- ReferencedType.cs
- ParameterSubsegment.cs
- DataSourceXmlSerializer.cs
- XmlSchemaInclude.cs
- DbConnectionPoolOptions.cs
- XmlHierarchicalDataSourceView.cs
- DependencyPropertyConverter.cs
- QueryActivatableWorkflowsCommand.cs
- WhitespaceRuleLookup.cs
- EntityDataSourceViewSchema.cs
- WrappedIUnknown.cs
- WebConfigurationManager.cs
- PropertyDescriptor.cs
- ObjectConverter.cs
- FlowDocumentScrollViewer.cs
- SqlClientMetaDataCollectionNames.cs
- SmtpClient.cs
- ExpressionConverter.cs
- MultiTrigger.cs
- SelfIssuedAuthRSAPKCS1SignatureFormatter.cs
- MarginCollapsingState.cs
- Boolean.cs
- TextEvent.cs
- CodeTypeConstructor.cs
- HttpCachePolicyElement.cs
- SimpleApplicationHost.cs
- DataTemplateSelector.cs
- SQLBoolean.cs
- RepeaterItemEventArgs.cs
- FunctionParameter.cs
- TokenCreationException.cs
- OleDbError.cs
- SectionInformation.cs
- ColorConvertedBitmapExtension.cs
- _LocalDataStoreMgr.cs
- HtmlTableRow.cs
- OrderToken.cs
- StructuredType.cs
- Axis.cs
- DocumentViewerConstants.cs
- RequestResizeEvent.cs
- DataGridCellsPanel.cs
- AggregatePushdown.cs
- SqlColumnizer.cs
- DoubleSumAggregationOperator.cs
- Button.cs
- GcHandle.cs
- UnsafeNativeMethods.cs
- QuotedPairReader.cs
- WindowVisualStateTracker.cs
- LocationReference.cs
- TripleDESCryptoServiceProvider.cs
- CaseKeyBox.ViewModel.cs
- DataGridCellInfo.cs
- WSSecureConversationDec2005.cs
- regiisutil.cs
- SchemaName.cs
- oledbconnectionstring.cs
- SplashScreen.cs
- loginstatus.cs
- TextMarkerSource.cs
- WebPartZoneDesigner.cs
- RichTextBoxAutomationPeer.cs
- LogWriteRestartAreaAsyncResult.cs
- errorpatternmatcher.cs
- SoapElementAttribute.cs
- XPathNodeList.cs
- DesignerPerfEventProvider.cs
- SessionStateSection.cs
- DatePickerTextBox.cs
- DateTimeFormat.cs
- SelectorAutomationPeer.cs
- QueryStack.cs
- MtomMessageEncodingBindingElement.cs
- PrintController.cs
- WindowsFormsSectionHandler.cs
- XmlIlGenerator.cs
- SecurityUniqueId.cs
- XmlNamespaceManager.cs
- COM2IPerPropertyBrowsingHandler.cs
- DataGridViewElement.cs
- ComponentCodeDomSerializer.cs
- Serializer.cs
- WebPartConnectionsDisconnectVerb.cs
- IdentityManager.cs
- CryptographicAttribute.cs
- CultureTable.cs
- XNodeNavigator.cs
- ProviderConnectionPointCollection.cs
- UnsafeNativeMethods.cs