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
- HyperLink.cs
- TransactionTraceIdentifier.cs
- ListView.cs
- MsmqChannelFactory.cs
- TypeTypeConverter.cs
- XmlNamedNodeMap.cs
- DemultiplexingDispatchMessageFormatter.cs
- QilCloneVisitor.cs
- COM2ColorConverter.cs
- PingOptions.cs
- XPathNavigator.cs
- ManifestBasedResourceGroveler.cs
- PropertyKey.cs
- XPathMessageFilterElement.cs
- AvTrace.cs
- HostProtectionException.cs
- Repeater.cs
- MediaContextNotificationWindow.cs
- AccessibleObject.cs
- MD5CryptoServiceProvider.cs
- SqlCacheDependencyDatabase.cs
- EntityKey.cs
- CodeDesigner.cs
- Help.cs
- Internal.cs
- DataBindEngine.cs
- Events.cs
- GridViewPageEventArgs.cs
- Aggregates.cs
- TemplateBindingExpression.cs
- StringSource.cs
- OdbcRowUpdatingEvent.cs
- XPathDocumentNavigator.cs
- ToolStripProgressBar.cs
- TagMapCollection.cs
- HttpContext.cs
- MetadataItem_Static.cs
- MemoryRecordBuffer.cs
- ToolStripProgressBar.cs
- PathSegmentCollection.cs
- HtmlTernaryTree.cs
- SEHException.cs
- RTLAwareMessageBox.cs
- SessionState.cs
- ValueExpressions.cs
- RenderCapability.cs
- UrlMappingCollection.cs
- recordstatescratchpad.cs
- AddInBase.cs
- ToolStripContentPanel.cs
- WindowsGraphicsCacheManager.cs
- XmlDataProvider.cs
- CryptoKeySecurity.cs
- xdrvalidator.cs
- KeyGestureConverter.cs
- WindowsSpinner.cs
- TraceListener.cs
- QueryContinueDragEvent.cs
- odbcmetadatacollectionnames.cs
- StrokeNodeOperations2.cs
- ELinqQueryState.cs
- EnumBuilder.cs
- WebWorkflowRole.cs
- ExpressionDumper.cs
- SqlServices.cs
- UnhandledExceptionEventArgs.cs
- exports.cs
- pingexception.cs
- TransactionManagerProxy.cs
- IndependentlyAnimatedPropertyMetadata.cs
- TopClause.cs
- IUnknownConstantAttribute.cs
- Graph.cs
- FlowDocumentReaderAutomationPeer.cs
- IpcChannel.cs
- OperatingSystemVersionCheck.cs
- WebDisplayNameAttribute.cs
- SmtpSection.cs
- ReadOnlyDataSourceView.cs
- InternalsVisibleToAttribute.cs
- PolicyManager.cs
- ToolStripCodeDomSerializer.cs
- SqlEnums.cs
- PtsHost.cs
- String.cs
- ObjectContext.cs
- MenuEventArgs.cs
- WebPartHeaderCloseVerb.cs
- CommandField.cs
- PaginationProgressEventArgs.cs
- AttachedAnnotationChangedEventArgs.cs
- DataSetUtil.cs
- xml.cs
- ProviderMetadata.cs
- SocketInformation.cs
- DllNotFoundException.cs
- AssemblyCache.cs
- WindowAutomationPeer.cs
- TrackingMemoryStream.cs
- PrivilegedConfigurationManager.cs