protected string GetHttpMethod(EntityStates state, ref Version requestVersion) { EntityStates states = state; if (states == EntityStates.Added) { return("POST"); } if (states != EntityStates.Deleted) { if (states != EntityStates.Modified) { throw System.Data.Services.Client.Error.InternalError(InternalError.UnvalidatedEntityState); } } else { return("DELETE"); } if (Util.IsFlagSet(this.Options, SaveChangesOptions.ReplaceOnUpdate)) { return("PUT"); } if (Util.IsFlagSet(this.Options, SaveChangesOptions.PatchOnUpdate)) { WebUtil.RaiseVersion(ref requestVersion, Util.DataServiceVersion3); return("PATCH"); } return("MERGE"); }
internal void VisitCountOptions() { this.uriBuilder.Append('$'); this.uriBuilder.Append("inlinecount"); this.uriBuilder.Append('='); this.uriBuilder.Append("allpages"); WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); }
internal override Expression VisitResourceSetExpression(ResourceSetExpression rse) { if (rse.NodeType == ((ExpressionType)0x2711)) { this.Visit(rse.Source); this.uriBuilder.Append('/').Append(this.ExpressionToString(rse.MemberExpression)); } else { string entitySetName = (string)((ConstantExpression)rse.MemberExpression).Value; this.uriBuilder.Append(this.context.BaseUriResolver.GetEntitySetUri(entitySetName)); } WebUtil.RaiseVersion(ref this.uriVersion, rse.UriVersion); if (rse.ResourceTypeAs != null) { this.uriBuilder.Append('/'); this.uriBuilder.Append(System.Data.Services.Client.UriHelper.GetEntityTypeNameForUriAndValidateMaxProtocolVersion(rse.ResourceTypeAs, this.context, ref this.uriVersion)); } if (rse.KeyPredicate != null) { this.uriBuilder.Append('('); if (rse.KeyPredicate.Count == 1) { this.uriBuilder.Append(this.ExpressionToString(rse.KeyPredicate.Values.First <ConstantExpression>())); } else { bool flag = false; foreach (KeyValuePair <PropertyInfo, ConstantExpression> pair in rse.KeyPredicate) { if (flag) { this.uriBuilder.Append(','); } this.uriBuilder.Append(pair.Key.Name); this.uriBuilder.Append('='); this.uriBuilder.Append(this.ExpressionToString(pair.Value)); flag = true; } } this.uriBuilder.Append(')'); } else if (rse == this.leafResourceSet) { this.uriBuilder.Append('('); this.uriBuilder.Append(')'); } if (rse.CountOption == CountOption.ValueOnly) { this.uriBuilder.Append('/').Append('$').Append("count"); WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); } this.VisitQueryOptions(rse); return(rse); }
internal static string ExpressionToString(DataServiceContext context, Expression e, ref Version uriVersion) { ExpressionWriter writer = new ExpressionWriter(context); string str = writer.Translate(e); WebUtil.RaiseVersion(ref uriVersion, writer.uriVersion); if (writer.cantTranslateExpression) { throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_CantTranslateExpression(e.ToString())); } return(str); }
private static Version DetermineRequestVersion(ClientTypeAnnotation clientType, EntityStates state) { if (state == EntityStates.Deleted) { return(Util.DataServiceVersion1); } Version version = Util.DataServiceVersion1; WebUtil.RaiseVersion(ref version, clientType.GetMetadataVersion()); WebUtil.RaiseVersion(ref version, clientType.EpmMinimumDataServiceProtocolVersion.ToVersion()); return(version); }
/// <summary> /// Serializes an expression to a string /// </summary> /// <param name='context'>Data context used to generate type names for types.</param> /// <param name="e">Expression to serialize</param> /// <param name='inPath'>Whether or not the expression being written is part of the path of the URI.</param> /// <param name="uriVersion">the request data service version for the uri</param> /// <returns>serialized expression</returns> internal static string ExpressionToString(DataServiceContext context, Expression e, bool inPath, ref Version uriVersion) { ExpressionWriter ew = new ExpressionWriter(context, inPath); string serialized = ew.Translate(e); WebUtil.RaiseVersion(ref uriVersion, ew.uriVersion); if (ew.cantTranslateExpression) { throw new NotSupportedException(Strings.ALinq_CantTranslateExpression(e.ToString())); } return(serialized); }
internal static string GetEntityTypeNameForUriAndValidateMaxProtocolVersion(Type type, DataServiceContext context, ref Version uriVersion) { if (context.MaxProtocolVersionAsVersion < Util.DataServiceVersion3) { throw new NotSupportedException(Strings.ALinq_TypeAsNotSupportedForMaxDataServiceVersionLessThan3); } if (!ClientTypeUtil.TypeOrElementTypeIsEntity(type)) { throw new NotSupportedException(Strings.ALinq_TypeAsArgumentNotEntityType(type.FullName)); } WebUtil.RaiseVersion(ref uriVersion, Util.DataServiceVersion3); return(context.ResolveNameFromType(type) ?? type.FullName); }
/// <summary> /// ResourceSetExpression visit method. /// </summary> /// <param name="rse">ResourceSetExpression expression to visit</param> /// <returns>Visited ResourceSetExpression expression</returns> internal override Expression VisitResourceSetExpression(ResourceSetExpression rse) { if ((ResourceExpressionType)rse.NodeType == ResourceExpressionType.ResourceNavigationProperty) { this.Visit(rse.Source); this.uriBuilder.Append(UriHelper.FORWARDSLASH).Append(this.ExpressionToString(rse.MemberExpression, /*inPath*/ true)); } else { // this is a resource set expression // we should be at the very begining of // the URI Debug.Assert(this.uriBuilder.Length == 0, "The builder is not empty while we are adding a resourset"); string entitySetName = (String)((ConstantExpression)rse.MemberExpression).Value; this.uriBuilder.Append(this.context.BaseUriResolver.GetEntitySetUri(entitySetName)); } WebUtil.RaiseVersion(ref this.uriVersion, rse.UriVersion); if (rse.ResourceTypeAs != null) { this.uriBuilder.Append(UriHelper.FORWARDSLASH); UriHelper.AppendTypeSegment(this.uriBuilder, rse.ResourceTypeAs, this.context, /*inPath*/ true, ref this.uriVersion); } if (rse.KeyPredicateConjuncts.Count > 0) { this.context.UrlConventions.AppendKeyExpression(rse.GetKeyProperties(), kvp => kvp.Key.Name, kvp => kvp.Value.Value, this.uriBuilder); } else if (rse == this.leafResourceSet) { // if resourceset is on the leaf, append () this.uriBuilder.Append(UriHelper.LEFTPAREN); this.uriBuilder.Append(UriHelper.RIGHTPAREN); } if (rse.CountOption == CountOption.ValueOnly) { // append $count segment: /$count this.uriBuilder.Append(UriHelper.FORWARDSLASH).Append(UriHelper.DOLLARSIGN).Append(UriHelper.COUNT); WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); } this.VisitQueryOptions(rse); return(rse); }
/// <summary>Gets the type name to be used in the URI for the given <paramref name="type"/>.</summary> /// <param name="type">Type to get name for.</param> /// <param name="context">Data context used to generate type names for types.</param> /// <param name="uriVersion">Data service version for the uri</param> /// <returns>The name for the <paramref name="type"/>, suitable for including in a URI.</returns> internal static string GetEntityTypeNameForUriAndValidateMaxProtocolVersion(Type type, DataServiceContext context, ref Version uriVersion) { Debug.Assert(type != null, "type != null"); Debug.Assert(context != null, "context != null"); if (context.MaxProtocolVersionAsVersion < Util.DataServiceVersion3) { throw new NotSupportedException(Strings.ALinq_TypeAsNotSupportedForMaxDataServiceVersionLessThan3); } if (!ClientTypeUtil.TypeOrElementTypeIsEntity(type)) { throw new NotSupportedException(Strings.ALinq_TypeAsArgumentNotEntityType(type.FullName)); } // Raise the uriVersion each time we write the type segment on the uri. WebUtil.RaiseVersion(ref uriVersion, Util.DataServiceVersion3); return(context.ResolveNameFromType(type) ?? type.FullName); }
internal void VisitProjectionPaths(List <string> paths) { this.uriBuilder.Append('$'); this.uriBuilder.Append("select"); this.uriBuilder.Append('='); int num = 0; while (true) { string str = paths[num]; this.uriBuilder.Append(str); if (++num == paths.Count) { break; } this.uriBuilder.Append(','); } WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); }
/// <summary> /// ProjectionPaths visit method. /// </summary> /// <param name="paths">Projection Paths</param> internal void VisitProjectionPaths(List <string> paths) { StringBuilder tmpBuilder = new StringBuilder(); int ii = 0; while (true) { string path = paths[ii]; tmpBuilder.Append(path); if (++ii == paths.Count) { break; } tmpBuilder.Append(UriHelper.COMMA); } this.AddAsCachedQueryOption(UriHelper.DOLLARSIGN + UriHelper.OPTIONSELECT, tmpBuilder.ToString()); WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); }
internal void VisitCustomQueryOptions(Dictionary <ConstantExpression, ConstantExpression> options) { List <ConstantExpression> list = options.Keys.ToList <ConstantExpression>(); List <ConstantExpression> list2 = options.Values.ToList <ConstantExpression>(); int num = 0; while (true) { this.uriBuilder.Append(list[num].Value); this.uriBuilder.Append('='); this.uriBuilder.Append(list2[num].Value); string str = list[num].Value.ToString(); if (str.Equals('$' + "inlinecount", StringComparison.Ordinal) || str.Equals('$' + "select", StringComparison.Ordinal)) { WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); } if (++num == list.Count) { return; } this.uriBuilder.Append('&'); } }
/// <summary> /// Append all cached query options to uri. /// </summary> private void AppendCachedQueryOptionsToUriBuilder() { int i = 0; foreach (var queryOption in this.cachedQueryOptions) { if (i++ != 0) { this.uriBuilder.Append(UriHelper.AMPERSAND); } string keyStr = queryOption.Key; string valueStr = string.Join(",", queryOption.Value); this.uriBuilder.Append(keyStr); this.uriBuilder.Append(UriHelper.EQUALSSIGN); this.uriBuilder.Append(valueStr); if (keyStr.Equals(UriHelper.DOLLARSIGN + UriHelper.OPTIONCOUNT, StringComparison.Ordinal) || keyStr.Equals(UriHelper.DOLLARSIGN + UriHelper.OPTIONSELECT, StringComparison.Ordinal)) { WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); } } }
internal void RaiseUriVersion(Version newVersion) { WebUtil.RaiseVersion(ref this.uriVersion, newVersion); }
/// <summary> /// VisitCountOptions visit method. /// </summary> internal void VisitCountOptions() { this.AddAsCachedQueryOption(UriHelper.DOLLARSIGN + UriHelper.OPTIONCOUNT, UriHelper.COUNTALL); WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion2); }
internal override Expression VisitMethodCall(MethodCallExpression m) { string str; SequenceMethod method; if (TypeSystem.TryGetQueryOptionMethod(m.Method, out str)) { this.builder.Append(str); this.builder.Append('('); if (str == "substringof") { this.Visit(m.Arguments[0]); this.builder.Append(','); this.Visit(m.Object); } else { if (m.Object != null) { this.Visit(m.Object); } if (m.Arguments.Count > 0) { if (m.Object != null) { this.builder.Append(','); } for (int i = 0; i < m.Arguments.Count; i++) { this.Visit(m.Arguments[i]); if (i < (m.Arguments.Count - 1)) { this.builder.Append(','); } } } } this.builder.Append(')'); return(m); } if (ReflectionUtil.TryIdentifySequenceMethod(m.Method, out method)) { if (ReflectionUtil.IsAnyAllMethod(method)) { WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion3); this.Visit(m.Arguments[0]); this.builder.Append('/'); if (method == SequenceMethod.All) { this.builder.Append("all"); } else { this.builder.Append("any"); } this.builder.Append('('); if (method != SequenceMethod.Any) { LambdaExpression expression = (LambdaExpression)m.Arguments[1]; string name = expression.Parameters[0].Name; this.builder.Append(name); this.builder.Append(':'); this.scopeCount++; this.Visit(expression.Body); this.scopeCount--; } this.builder.Append(')'); return(m); } if ((method == SequenceMethod.OfType) && (this.parent != null)) { MethodCallExpression parent = this.parent as MethodCallExpression; if (((parent != null) && ReflectionUtil.TryIdentifySequenceMethod(parent.Method, out method)) && ReflectionUtil.IsAnyAllMethod(method)) { Type type = parent.Method.GetGenericArguments().SingleOrDefault <Type>(); if (ClientTypeUtil.TypeOrElementTypeIsEntity(type)) { this.Visit(m.Arguments[0]); this.builder.Append('/'); this.builder.Append(System.Data.Services.Client.UriHelper.GetEntityTypeNameForUriAndValidateMaxProtocolVersion(type, this.context, ref this.uriVersion)); return(m); } } } } this.cantTranslateExpression = true; return(m); }
/// <summary> /// MethodCallExpression visit method /// </summary> /// <param name="m">The MethodCallExpression expression to visit</param> /// <returns>The visited MethodCallExpression expression </returns> internal override Expression VisitMethodCall(MethodCallExpression m) { string methodName; if (TypeSystem.TryGetQueryOptionMethod(m.Method, out methodName)) { this.builder.Append(methodName); this.builder.Append(UriHelper.LEFTPAREN); // There is a single function, 'substringof', which reorders its argument with // respect to the CLR method. Thus handling it as a special case rather than // using a more general argument reordering mechanism. if (methodName == "substringof") { Debug.Assert(m.Method.Name == "Contains", "m.Method.Name == 'Contains'"); Debug.Assert(m.Object != null, "m.Object != null"); Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1"); this.Visit(m.Arguments[0]); this.builder.Append(UriHelper.COMMA); this.Visit(m.Object); } else { if (m.Object != null) { this.Visit(m.Object); } if (m.Arguments.Count > 0) { if (m.Object != null) { this.builder.Append(UriHelper.COMMA); } for (int ii = 0; ii < m.Arguments.Count; ii++) { this.Visit(m.Arguments[ii]); if (ii < m.Arguments.Count - 1) { this.builder.Append(UriHelper.COMMA); } } } } this.builder.Append(UriHelper.RIGHTPAREN); } else { SequenceMethod sequenceMethod; if (ReflectionUtil.TryIdentifySequenceMethod(m.Method, out sequenceMethod)) { if (ReflectionUtil.IsAnyAllMethod(sequenceMethod)) { // Raise the uriVersion each time we write any or all methods to the uri. WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion3); this.Visit(m.Arguments[0]); this.builder.Append(UriHelper.FORWARDSLASH); if (sequenceMethod == SequenceMethod.All) { this.builder.Append(XmlConstants.AllMethodName); } else { this.builder.Append(XmlConstants.AnyMethodName); } this.builder.Append(UriHelper.LEFTPAREN); if (sequenceMethod != SequenceMethod.Any) { // SequenceMethod.Any represents Enumerable.Any(), which has only source argument // AnyPredicate and All has a second parameter which is the predicate lambda. Debug.Assert(m.Arguments.Count() == 2, "m.Arguments.Count() == 2"); LambdaExpression le = (LambdaExpression)m.Arguments[1]; string rangeVariable = le.Parameters[0].Name; this.builder.Append(rangeVariable); this.builder.Append(UriHelper.COLON); this.scopeCount++; this.Visit(le.Body); this.scopeCount--; } this.builder.Append(UriHelper.RIGHTPAREN); return(m); } else if (sequenceMethod == SequenceMethod.OfType && this.parent != null) { // check to see if this is an OfType filter for Any or All. // e.g. ctx.CreateQuery<Movie>("Movies").Where(m=>m.Actors.OfType<MegaStar>().Any()) // which translates to /Movies()?$filter=Actors/MegaStar/any() MethodCallExpression mce = this.parent as MethodCallExpression; if (mce != null && ReflectionUtil.TryIdentifySequenceMethod(mce.Method, out sequenceMethod) && ReflectionUtil.IsAnyAllMethod(sequenceMethod)) { Type filteredType = mce.Method.GetGenericArguments().SingleOrDefault(); if (ClientTypeUtil.TypeOrElementTypeIsEntity(filteredType)) { this.Visit(m.Arguments[0]); this.builder.Append(UriHelper.FORWARDSLASH); UriHelper.AppendTypeSegment(this.builder, filteredType, this.context, this.inPath, ref this.uriVersion); return(m); } } } } this.cantTranslateExpression = true; } return(m); }
/// <summary>Raise the UriVersion if it is lower than <paramref name="newVersion"/>.</summary> /// <param name="newVersion">Uri version from the expand and projection paths</param> internal void RaiseUriVersion(Version newVersion) { Debug.Assert(newVersion != null, "newVersion != null"); WebUtil.RaiseVersion(ref this.uriVersion, newVersion); }