/mcs/class/System.Data.Services.Client/Client/System/Data/Services/Client/DataServiceContext.cs
C# | 4908 lines | 4024 code | 873 blank | 11 comment | 935 complexity | 4e5d044121c43696f18b2edfc18d037a MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- //Copyright 2010 Microsoft Corporation
- //
- //Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
- //You may obtain a copy of the License at
- //
- //http://www.apache.org/licenses/LICENSE-2.0
- //
- //Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- //"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- //See the License for the specific language governing permissions and limitations under the License.
-
-
-
- namespace System.Data.Services.Client
- {
- #region Namespaces.
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Data.Services.Common;
- #if !ASTORIA_LIGHT
- using System.Net;
- #else
- using System.Data.Services.Http;
- #endif
- using System.Text;
- using System.Xml;
- using System.Xml.Linq;
-
- #endregion Namespaces.
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506", Justification = "Central class of the API, likely to have many cross-references")]
- public class DataServiceContext
- {
- #if !TESTUNIXNEWLINE
- private static readonly string NewLine = System.Environment.NewLine;
- #else
- private const string NewLine = "\n";
- #endif
-
- private readonly System.Uri baseUri;
-
- private readonly System.Uri baseUriWithSlash;
-
- #if !ASTORIA_LIGHT
- private System.Net.ICredentials credentials;
- #endif
-
- private string dataNamespace;
-
- private Func<Type, string> resolveName;
-
- private Func<string, Type> resolveType;
-
- #if !ASTORIA_LIGHT
- private int timeout;
- #endif
-
- private bool postTunneling;
-
- private bool ignoreMissingProperties;
-
- private MergeOption mergeOption;
-
- private SaveChangesOptions saveChangesDefaultOptions;
-
- private Uri typeScheme;
-
- private bool ignoreResourceNotFoundException;
-
- #if ASTORIA_LIGHT
- private HttpStack httpStack;
- #endif
-
- #region Resource state management
-
- private uint nextChange;
-
- private Dictionary<object, EntityDescriptor> entityDescriptors = new Dictionary<object, EntityDescriptor>(EqualityComparer<object>.Default);
-
- private Dictionary<String, EntityDescriptor> identityToDescriptor;
-
- private Dictionary<LinkDescriptor, LinkDescriptor> bindings = new Dictionary<LinkDescriptor, LinkDescriptor>(LinkDescriptor.EquivalenceComparer);
-
- private bool applyingChanges;
-
- #endregion
-
- #region ctor
-
- public DataServiceContext(Uri serviceRoot)
- {
- Util.CheckArgumentNull(serviceRoot, "serviceRoot");
-
- #if ASTORIA_LIGHT
- if (!serviceRoot.IsAbsoluteUri)
- {
- if (XHRHttpWebRequest.IsAvailable())
- {
- serviceRoot = new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, serviceRoot);
- }
- else
- {
- System.Net.WebClient webClient = new System.Net.WebClient();
- serviceRoot = new Uri(new Uri(webClient.BaseAddress), serviceRoot);
- }
- }
- #endif
- if (!serviceRoot.IsAbsoluteUri ||
- !Uri.IsWellFormedUriString(serviceRoot.OriginalString, UriKind.Absolute) ||
- !String.IsNullOrEmpty(serviceRoot.Query) ||
- !string.IsNullOrEmpty(serviceRoot.Fragment) ||
- ((serviceRoot.Scheme != "http") && (serviceRoot.Scheme != "https")))
- {
- throw Error.Argument(Strings.Context_BaseUri, "serviceRoot");
- }
-
- this.baseUri = serviceRoot;
- this.baseUriWithSlash = serviceRoot;
- if (!serviceRoot.OriginalString.EndsWith("/", StringComparison.Ordinal))
- {
- this.baseUriWithSlash = Util.CreateUri(serviceRoot.OriginalString + "/", UriKind.Absolute);
- }
-
- this.mergeOption = MergeOption.AppendOnly;
- this.DataNamespace = XmlConstants.DataWebNamespace;
- #if ASTORIA_LIGHT
- this.UsePostTunneling = true;
- #else
- this.UsePostTunneling = false;
- #endif
- this.typeScheme = new Uri(XmlConstants.DataWebSchemeNamespace);
- #if ASTORIA_LIGHT
- this.httpStack = HttpStack.Auto;
- #endif
- }
-
- #endregion
-
- public event EventHandler<SendingRequestEventArgs> SendingRequest;
-
- public event EventHandler<ReadingWritingEntityEventArgs> ReadingEntity;
-
- public event EventHandler<ReadingWritingEntityEventArgs> WritingEntity;
-
- internal event EventHandler<SaveChangesEventArgs> ChangesSaved;
-
- #region BaseUri, Credentials, MergeOption, Timeout, Links, Entities
- public Uri BaseUri
- {
- get { return this.baseUri; }
- }
-
- #if !ASTORIA_LIGHT
- public System.Net.ICredentials Credentials
- {
- get { return this.credentials; }
- set { this.credentials = value; }
- }
- #endif
-
- public MergeOption MergeOption
- {
- get { return this.mergeOption; }
- set { this.mergeOption = Util.CheckEnumerationValue(value, "MergeOption"); }
- }
-
- public bool ApplyingChanges
- {
- get { return this.applyingChanges; }
- internal set { this.applyingChanges = value; }
- }
-
- public bool IgnoreMissingProperties
- {
- get { return this.ignoreMissingProperties; }
- set { this.ignoreMissingProperties = value; }
- }
-
- public string DataNamespace
- {
- get
- {
- return this.dataNamespace;
- }
-
- set
- {
- Util.CheckArgumentNull(value, "value");
- this.dataNamespace = value;
- }
- }
-
- public Func<Type, string> ResolveName
- {
- get { return this.resolveName; }
- set { this.resolveName = value; }
- }
-
- public Func<string, Type> ResolveType
- {
- get { return this.resolveType; }
- set { this.resolveType = value; }
- }
-
- #if !ASTORIA_LIGHT
- public int Timeout
- {
- get
- {
- return this.timeout;
- }
-
- set
- {
- if (value < 0)
- {
- throw Error.ArgumentOutOfRange("Timeout");
- }
-
- this.timeout = value;
- }
- }
- #endif
-
- public Uri TypeScheme
- {
- get
- {
- return this.typeScheme;
- }
-
- set
- {
- Util.CheckArgumentNull(value, "value");
- this.typeScheme = value;
- }
- }
-
- public bool UsePostTunneling
- {
- get { return this.postTunneling; }
- set { this.postTunneling = value; }
- }
-
- public ReadOnlyCollection<LinkDescriptor> Links
- {
- get
- {
- return this.bindings.Values.OrderBy(l => l.ChangeOrder).ToList().AsReadOnly();
- }
- }
-
- public ReadOnlyCollection<EntityDescriptor> Entities
- {
- get
- {
- return this.entityDescriptors.Values.OrderBy(d => d.ChangeOrder).ToList().AsReadOnly();
- }
- }
-
- public SaveChangesOptions SaveChangesDefaultOptions
- {
- get
- {
- return this.saveChangesDefaultOptions;
- }
-
- set
- {
- ValidateSaveChangesOptions(value);
- this.saveChangesDefaultOptions = value;
- }
- }
-
- #endregion
-
- public bool IgnoreResourceNotFoundException
- {
- get { return this.ignoreResourceNotFoundException; }
- set { this.ignoreResourceNotFoundException = value; }
- }
-
- #if ASTORIA_LIGHT
- public HttpStack HttpStack
- {
- get { return this.httpStack; }
- set { this.httpStack = Util.CheckEnumerationValue(value, "HttpStack"); }
- }
- #endif
-
- internal Uri BaseUriWithSlash
- {
- get { return this.baseUriWithSlash; }
- }
-
- internal bool HasReadingEntityHandlers
- {
- [DebuggerStepThrough]
- get { return this.ReadingEntity != null; }
- }
-
- #region Entity and Link Tracking
-
- public EntityDescriptor GetEntityDescriptor(object entity)
- {
- Util.CheckArgumentNull(entity, "entity");
-
- EntityDescriptor descriptor;
- if (this.entityDescriptors.TryGetValue(entity, out descriptor))
- {
- return descriptor;
- }
- else
- {
- return null;
- }
- }
-
- public LinkDescriptor GetLinkDescriptor(object source, string sourceProperty, object target)
- {
- Util.CheckArgumentNull(source, "source");
- Util.CheckArgumentNotEmpty(sourceProperty, "sourceProperty");
- Util.CheckArgumentNull(target, "target");
-
- LinkDescriptor link;
-
- if (this.bindings.TryGetValue(new LinkDescriptor(source, sourceProperty, target), out link))
- {
- return link;
- }
- else
- {
- return null;
- }
- }
-
- #endregion
-
- #region CancelRequest
- public void CancelRequest(IAsyncResult asyncResult)
- {
- Util.CheckArgumentNull(asyncResult, "asyncResult");
- BaseAsyncResult result = asyncResult as BaseAsyncResult;
-
- if ((null == result) || (this != result.Source))
- {
- object context = null;
- DataServiceQuery query = null;
- if (null != result)
- {
- query = result.Source as DataServiceQuery;
-
- if (null != query)
- {
- DataServiceQueryProvider provider = query.Provider as DataServiceQueryProvider;
- if (null != provider)
- {
- context = provider.Context;
- }
- }
- }
-
- if (this != context)
- {
- throw Error.Argument(Strings.Context_DidNotOriginateAsync, "asyncResult");
- }
- }
-
- if (!result.IsCompletedInternally)
- {
- result.SetAborted();
-
- WebRequest request = result.Abortable;
- if (null != request)
- {
- request.Abort();
- }
- }
- }
- #endregion
-
- #region CreateQuery
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "required for this feature")]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "required for this feature")]
- public DataServiceQuery<T> CreateQuery<T>(string entitySetName)
- {
- Util.CheckArgumentNotEmpty(entitySetName, "entitySetName");
- this.ValidateEntitySetName(ref entitySetName);
-
- ResourceSetExpression rse = new ResourceSetExpression(typeof(IOrderedQueryable<T>), null, Expression.Constant(entitySetName), typeof(T), null, CountOption.None, null, null);
- return new DataServiceQuery<T>.DataServiceOrderedQuery(rse, new DataServiceQueryProvider(this));
- }
- #endregion
-
- #region GetMetadataUri
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "required for this feature")]
- public Uri GetMetadataUri()
- {
- Uri metadataUri = Util.CreateUri(this.baseUriWithSlash.OriginalString + XmlConstants.UriMetadataSegment, UriKind.Absolute);
- return metadataUri;
- }
- #endregion
-
- #region LoadProperty
-
- public IAsyncResult BeginLoadProperty(object entity, string propertyName, AsyncCallback callback, object state)
- {
- return this.BeginLoadProperty(entity, propertyName, (Uri)null, callback, state);
- }
-
- public IAsyncResult BeginLoadProperty(object entity, string propertyName, Uri nextLinkUri, AsyncCallback callback, object state)
- {
- LoadPropertyResult result = this.CreateLoadPropertyRequest(entity, propertyName, callback, state, nextLinkUri, null);
- result.BeginExecute();
- return result;
- }
-
- public IAsyncResult BeginLoadProperty(object entity, string propertyName, DataServiceQueryContinuation continuation, AsyncCallback callback, object state)
- {
- Util.CheckArgumentNull(continuation, "continuation");
- LoadPropertyResult result = this.CreateLoadPropertyRequest(entity, propertyName, callback, state, null, continuation);
- result.BeginExecute();
- return result;
- }
-
- public QueryOperationResponse EndLoadProperty(IAsyncResult asyncResult)
- {
- LoadPropertyResult response = QueryResult.EndExecute<LoadPropertyResult>(this, "LoadProperty", asyncResult);
- return response.LoadProperty();
- }
-
- #if !ASTORIA_LIGHT
- public QueryOperationResponse LoadProperty(object entity, string propertyName)
- {
- return this.LoadProperty(entity, propertyName, (Uri)null);
- }
-
- public QueryOperationResponse LoadProperty(object entity, string propertyName, Uri nextLinkUri)
- {
- LoadPropertyResult result = this.CreateLoadPropertyRequest(entity, propertyName, null, null, nextLinkUri, null);
- result.Execute();
- return result.LoadProperty();
- }
-
- public QueryOperationResponse LoadProperty(object entity, string propertyName, DataServiceQueryContinuation continuation)
- {
- LoadPropertyResult result = this.CreateLoadPropertyRequest(entity, propertyName, null, null, null, continuation);
- result.Execute();
- return result.LoadProperty();
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011", Justification = "allows compiler to infer 'T'")]
- public QueryOperationResponse<T> LoadProperty<T>(object entity, string propertyName, DataServiceQueryContinuation<T> continuation)
- {
- LoadPropertyResult result = this.CreateLoadPropertyRequest(entity, propertyName, null, null, null, continuation);
- result.Execute();
- return (QueryOperationResponse<T>)result.LoadProperty();
- }
-
- #endif
- #endregion
-
- #region GetReadStreamUri
- public Uri GetReadStreamUri(object entity)
- {
- EntityDescriptor box = this.EnsureContained(entity, "entity");
- return box.GetMediaResourceUri(this.baseUriWithSlash);
- }
- #endregion
-
- #region GetReadStream, BeginGetReadStream, EndGetReadStream
-
- public IAsyncResult BeginGetReadStream(object entity, DataServiceRequestArgs args, AsyncCallback callback, object state)
- {
- GetReadStreamResult result;
- result = this.CreateGetReadStreamResult(entity, args, callback, state);
- result.Begin();
- return result;
- }
-
- public DataServiceStreamResponse EndGetReadStream(IAsyncResult asyncResult)
- {
- GetReadStreamResult result = BaseAsyncResult.EndExecute<GetReadStreamResult>(this, "GetReadStream", asyncResult);
- return result.End();
- }
-
- #if !ASTORIA_LIGHT
- public DataServiceStreamResponse GetReadStream(object entity)
- {
- DataServiceRequestArgs args = new DataServiceRequestArgs();
- return this.GetReadStream(entity, args);
- }
-
- public DataServiceStreamResponse GetReadStream(object entity, string acceptContentType)
- {
- Util.CheckArgumentNotEmpty(acceptContentType, "acceptContentType");
- DataServiceRequestArgs args = new DataServiceRequestArgs();
- args.AcceptContentType = acceptContentType;
- return this.GetReadStream(entity, args);
- }
-
- public DataServiceStreamResponse GetReadStream(object entity, DataServiceRequestArgs args)
- {
- GetReadStreamResult result = this.CreateGetReadStreamResult(entity, args, null, null);
- return result.Execute();
- }
-
- #endif
- #endregion
-
- #region SetSaveStream
-
- public void SetSaveStream(object entity, Stream stream, bool closeStream, string contentType, string slug)
- {
- Util.CheckArgumentNull(contentType, "contentType");
- Util.CheckArgumentNull(slug, "slug");
-
- DataServiceRequestArgs args = new DataServiceRequestArgs();
- args.ContentType = contentType;
- args.Slug = slug;
- this.SetSaveStream(entity, stream, closeStream, args);
- }
-
- public void SetSaveStream(object entity, Stream stream, bool closeStream, DataServiceRequestArgs args)
- {
- EntityDescriptor box = this.EnsureContained(entity, "entity");
- Util.CheckArgumentNull(stream, "stream");
- Util.CheckArgumentNull(args, "args");
-
- ClientType clientType = ClientType.Create(entity.GetType());
- if (clientType.MediaDataMember != null)
- {
- throw new ArgumentException(
- Strings.Context_SetSaveStreamOnMediaEntryProperty(clientType.ElementTypeName),
- "entity");
- }
-
- box.SaveStream = new DataServiceSaveStream(stream, closeStream, args);
-
- Debug.Assert(box.State != EntityStates.Detached, "We should never have a detached entity in the entityDescriptor dictionary.");
- switch (box.State)
- {
- case EntityStates.Added:
- box.StreamState = StreamStates.Added;
- break;
-
- case EntityStates.Modified:
- case EntityStates.Unchanged:
- box.StreamState = StreamStates.Modified;
- break;
-
- case EntityStates.Deleted:
- default:
- throw new DataServiceClientException(Strings.DataServiceException_GeneralError);
- }
-
- }
-
- #endregion
-
- #region ExecuteBatch, BeginExecuteBatch, EndExecuteBatch
-
- public IAsyncResult BeginExecuteBatch(AsyncCallback callback, object state, params DataServiceRequest[] queries)
- {
- Util.CheckArgumentNotEmpty(queries, "queries");
-
- SaveResult result = new SaveResult(this, "ExecuteBatch", queries, SaveChangesOptions.Batch, callback, state, true);
- result.BatchBeginRequest(false);
- return result;
- }
-
-
- public DataServiceResponse EndExecuteBatch(IAsyncResult asyncResult)
- {
- SaveResult result = BaseAsyncResult.EndExecute<SaveResult>(this, "ExecuteBatch", asyncResult);
- return result.EndRequest();
- }
-
- #if !ASTORIA_LIGHT
- public DataServiceResponse ExecuteBatch(params DataServiceRequest[] queries)
- {
- Util.CheckArgumentNotEmpty(queries, "queries");
-
- SaveResult result = new SaveResult(this, "ExecuteBatch", queries, SaveChangesOptions.Batch, null, null, false);
- result.BatchRequest(false );
- return result.EndRequest();
- }
- #endif
-
- #endregion
-
- #region Execute(Uri), BeginExecute(Uri), EndExecute(Uri)
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Type is used to infer result")]
- public IAsyncResult BeginExecute<TElement>(Uri requestUri, AsyncCallback callback, object state)
- {
- requestUri = Util.CreateUri(this.baseUriWithSlash, requestUri);
- QueryComponents qc = new QueryComponents(requestUri, Util.DataServiceVersionEmpty, typeof(TElement), null, null);
- return (new DataServiceRequest<TElement>(qc, null)).BeginExecute(this, this, callback, state);
- }
-
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Type is used to infer result")]
- public IAsyncResult BeginExecute<T>(DataServiceQueryContinuation<T> continuation, AsyncCallback callback, object state)
- {
- Util.CheckArgumentNull(continuation, "continuation");
- QueryComponents qc = continuation.CreateQueryComponents();
- return (new DataServiceRequest<T>(qc, continuation.Plan)).BeginExecute(this, this, callback, state);
- }
-
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Type is used to infer result")]
- public IEnumerable<TElement> EndExecute<TElement>(IAsyncResult asyncResult)
- {
- Util.CheckArgumentNull(asyncResult, "asyncResult");
- return DataServiceRequest.EndExecute<TElement>(this, this, asyncResult);
- }
-
- #if !ASTORIA_LIGHT
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Type is used to infer result")]
- public IEnumerable<TElement> Execute<TElement>(Uri requestUri)
- {
- requestUri = Util.CreateUri(this.baseUriWithSlash, requestUri);
- QueryComponents qc = new QueryComponents(requestUri, Util.DataServiceVersionEmpty, typeof(TElement), null, null);
- DataServiceRequest request = new DataServiceRequest<TElement>(qc, null);
- return request.Execute<TElement>(this, qc);
- }
-
- public QueryOperationResponse<T> Execute<T>(DataServiceQueryContinuation<T> continuation)
- {
- Util.CheckArgumentNull(continuation, "continuation");
- QueryComponents qc = continuation.CreateQueryComponents();
- DataServiceRequest request = new DataServiceRequest<T>(qc, continuation.Plan);
- return request.Execute<T>(this, qc);
- }
- #endif
- #endregion
-
- #region SaveChanges, BeginSaveChanges, EndSaveChanges
-
-
- public IAsyncResult BeginSaveChanges(AsyncCallback callback, object state)
- {
- return this.BeginSaveChanges(this.SaveChangesDefaultOptions, callback, state);
- }
-
-
- public IAsyncResult BeginSaveChanges(SaveChangesOptions options, AsyncCallback callback, object state)
- {
- ValidateSaveChangesOptions(options);
- SaveResult result = new SaveResult(this, "SaveChanges", null, options, callback, state, true);
- bool replaceOnUpdate = IsFlagSet(options, SaveChangesOptions.ReplaceOnUpdate);
- if (IsFlagSet(options, SaveChangesOptions.Batch))
- {
- result.BatchBeginRequest(replaceOnUpdate);
- }
- else
- {
- result.BeginNextChange(replaceOnUpdate);
- }
-
- return result;
- }
-
- public DataServiceResponse EndSaveChanges(IAsyncResult asyncResult)
- {
- SaveResult result = BaseAsyncResult.EndExecute<SaveResult>(this, "SaveChanges", asyncResult);
-
- DataServiceResponse errors = result.EndRequest();
-
- if (this.ChangesSaved != null)
- {
- this.ChangesSaved(this, new SaveChangesEventArgs(errors));
- }
-
- return errors;
- }
-
- #if !ASTORIA_LIGHT
- public DataServiceResponse SaveChanges()
- {
- return this.SaveChanges(this.SaveChangesDefaultOptions);
- }
-
-
- public DataServiceResponse SaveChanges(SaveChangesOptions options)
- {
- DataServiceResponse errors = null;
- ValidateSaveChangesOptions(options);
-
- SaveResult result = new SaveResult(this, "SaveChanges", null, options, null, null, false);
- bool replaceOnUpdate = IsFlagSet(options, SaveChangesOptions.ReplaceOnUpdate);
- if (IsFlagSet(options, SaveChangesOptions.Batch))
- {
- result.BatchRequest(replaceOnUpdate);
- }
- else
- {
- result.BeginNextChange(replaceOnUpdate);
- }
-
- errors = result.EndRequest();
-
- Debug.Assert(null != errors, "null errors");
-
- if (this.ChangesSaved != null)
- {
- this.ChangesSaved(this, new SaveChangesEventArgs(errors));
- }
-
- return errors;
- }
- #endif
- #endregion
-
- #region Add, Attach, Delete, Detach, Update, TryGetEntity, TryGetUri
-
-
- public void AddLink(object source, string sourceProperty, object target)
- {
- this.EnsureRelatable(source, sourceProperty, target, EntityStates.Added);
-
- LinkDescriptor relation = new LinkDescriptor(source, sourceProperty, target);
- if (this.bindings.ContainsKey(relation))
- {
- throw Error.InvalidOperation(Strings.Context_RelationAlreadyContained);
- }
-
- relation.State = EntityStates.Added;
- this.bindings.Add(relation, relation);
- this.IncrementChange(relation);
- }
-
-
- public void AttachLink(object source, string sourceProperty, object target)
- {
- this.AttachLink(source, sourceProperty, target, MergeOption.NoTracking);
- }
-
-
- public bool DetachLink(object source, string sourceProperty, object target)
- {
- Util.CheckArgumentNull(source, "source");
- Util.CheckArgumentNotEmpty(sourceProperty, "sourceProperty");
-
- LinkDescriptor existing;
- LinkDescriptor relation = new LinkDescriptor(source, sourceProperty, target);
- if (!this.bindings.TryGetValue(relation, out existing))
- {
- return false;
- }
-
- this.DetachExistingLink(existing, false);
- return true;
- }
-
-
- public void DeleteLink(object source, string sourceProperty, object target)
- {
- bool delay = this.EnsureRelatable(source, sourceProperty, target, EntityStates.Deleted);
-
- LinkDescriptor existing = null;
- LinkDescriptor relation = new LinkDescriptor(source, sourceProperty, target);
- if (this.bindings.TryGetValue(relation, out existing) && (EntityStates.Added == existing.State))
- {
- this.DetachExistingLink(existing, false);
- }
- else
- {
- if (delay)
- {
- throw Error.InvalidOperation(Strings.Context_NoRelationWithInsertEnd);
- }
-
- if (null == existing)
- {
- this.bindings.Add(relation, relation);
- existing = relation;
- }
-
- if (EntityStates.Deleted != existing.State)
- {
- existing.State = EntityStates.Deleted;
-
-
- this.IncrementChange(existing);
- }
- }
- }
-
-
- public void SetLink(object source, string sourceProperty, object target)
- {
- this.EnsureRelatable(source, sourceProperty, target, EntityStates.Modified);
-
- LinkDescriptor relation = this.DetachReferenceLink(source, sourceProperty, target, MergeOption.NoTracking);
- if (null == relation)
- {
- relation = new LinkDescriptor(source, sourceProperty, target);
- this.bindings.Add(relation, relation);
- }
-
- Debug.Assert(
- 0 == relation.State ||
- IncludeLinkState(relation.State),
- "set link entity state");
-
- if (EntityStates.Modified != relation.State)
- {
- relation.State = EntityStates.Modified;
- this.IncrementChange(relation);
- }
- }
-
- #endregion
-
- #region AddObject, AttachTo, DeleteObject, Detach, TryGetEntity, TryGetUri
-
- public void AddObject(string entitySetName, object entity)
- {
- this.ValidateEntitySetName(ref entitySetName);
- ValidateEntityType(entity);
-
- EntityDescriptor resource = new EntityDescriptor(null, null , null , entity, null, null, entitySetName, null, EntityStates.Added);
-
- try
- {
- this.entityDescriptors.Add(entity, resource);
- }
- catch (ArgumentException)
- {
- throw Error.InvalidOperation(Strings.Context_EntityAlreadyContained);
- }
-
- this.IncrementChange(resource);
- }
-
-
- public void AddRelatedObject(object source, string sourceProperty, object target)
- {
- Util.CheckArgumentNull(source, "source");
- Util.CheckArgumentNotEmpty(sourceProperty, "propertyName");
- Util.CheckArgumentNull(target, "target");
-
-
- ValidateEntityType(source);
-
- EntityDescriptor sourceResource = this.EnsureContained(source, "source");
-
-
- if (sourceResource.State == EntityStates.Deleted)
- {
- throw Error.InvalidOperation(Strings.Context_AddRelatedObjectSourceDeleted);
- }
-
- ClientType parentType = ClientType.Create(source.GetType());
- ClientType.ClientProperty property = parentType.GetProperty(sourceProperty, false);
- if (property.IsKnownType || property.CollectionType == null)
- {
- throw Error.InvalidOperation(Strings.Context_AddRelatedObjectCollectionOnly);
- }
-
-
- ClientType childType = ClientType.Create(target.GetType());
- ValidateEntityType(target);
-
-
- ClientType propertyElementType = ClientType.Create(property.CollectionType);
- if (!propertyElementType.ElementType.IsAssignableFrom(childType.ElementType))
- {
-
- throw Error.Argument(Strings.Context_RelationNotRefOrCollection, "target");
- }
-
- EntityDescriptor targetResource = new EntityDescriptor(null, null, null, target, sourceResource, sourceProperty, null , null, EntityStates.Added);
-
- try
- {
- this.entityDescriptors.Add(target, targetResource);
- }
- catch (ArgumentException)
- {
- throw Error.InvalidOperation(Strings.Context_EntityAlreadyContained);
- }
-
-
- LinkDescriptor end = targetResource.GetRelatedEnd();
- end.State = EntityStates.Added;
- this.bindings.Add(end, end);
-
- this.IncrementChange(targetResource);
- }
-
-
- public void AttachTo(string entitySetName, object entity)
- {
- this.AttachTo(entitySetName, entity, null);
- }
-
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704", MessageId = "etag", Justification = "represents ETag in request")]
- public void AttachTo(string entitySetName, object entity, string etag)
- {
- this.ValidateEntitySetName(ref entitySetName);
- Uri editLink = GenerateEditLinkUri(this.baseUriWithSlash, entitySetName, entity);
-
-
- String identity = Util.ReferenceIdentity(editLink.ToString());
-
- EntityDescriptor descriptor = new EntityDescriptor(identity, null , editLink, entity, null , null , null , etag, EntityStates.Unchanged);
- this.InternalAttachEntityDescriptor(descriptor, true);
- }
-
-
- public void DeleteObject(object entity)
- {
- Util.CheckArgumentNull(entity, "entity");
-
- EntityDescriptor resource = null;
- if (!this.entityDescriptors.TryGetValue(entity, out resource))
- {
- throw Error.InvalidOperation(Strings.Context_EntityNotContained);
- }
-
- EntityStates state = resource.State;
- if (EntityStates.Added == state)
- {
- this.DetachResource(resource);
- }
- else if (EntityStates.Deleted != state)
- {
- Debug.Assert(
- IncludeLinkState(state),
- "bad state transition to deleted");
-
-
- resource.State = EntityStates.Deleted;
- this.IncrementChange(resource);
- }
- }
-
- public bool Detach(object entity)
- {
- Util.CheckArgumentNull(entity, "entity");
-
- EntityDescriptor resource = null;
- if (this.entityDescriptors.TryGetValue(entity, out resource))
- {
- return this.DetachResource(resource);
- }
-
- return false;
- }
-
-
- public void UpdateObject(object entity)
- {
- Util.CheckArgumentNull(entity, "entity");
-
- EntityDescriptor resource = null;
- if (!this.entityDescriptors.TryGetValue(entity, out resource))
- {
- throw Error.Argument(Strings.Context_EntityNotContained, "entity");
- }
-
- if (EntityStates.Unchanged == resource.State)
- {
- resource.State = EntityStates.Modified;
- this.IncrementChange(resource);
- }
- }
-
- public bool TryGetEntity<TEntity>(Uri identity, out TEntity entity) where TEntity : class
- {
- entity = null;
- Util.CheckArgumentNull(identity, "relativeUri");
-
- EntityStates state;
-
-
- entity = (TEntity)this.TryGetEntity(Util.ReferenceIdentity(identity.ToString()), null, MergeOption.AppendOnly, out state);
- return (null != entity);
- }
-
-
- public bool TryGetUri(object entity, out Uri identity)
- {
- identity = null;
- Util.CheckArgumentNull(entity, "entity");
-
- EntityDescriptor resource = null;
- if ((null != this.identityToDescriptor) &&
- this.entityDescriptors.TryGetValue(entity, out resource) &&
- (null != resource.Identity) &&
- Object.ReferenceEquals(resource, this.identityToDescriptor[resource.Identity]))
- {
-
- string identityUri = Util.DereferenceIdentity(resource.Identity);
- identity = Util.CreateUri(identityUri, UriKind.Absolute);
- }
-
- return (null != identity);
- }
-
- internal static Exception HandleResponse(
- HttpStatusCode statusCode,
- string responseVersion,
- Func<Stream> getResponseStream,
- bool throwOnFailure)
- {
- InvalidOperationException failure = null;
- if (!CanHandleResponseVersion(responseVersion))
- {
- string description = Strings.Context_VersionNotSupported(
- responseVersion,
- SerializeSupportedVersions());
-
- failure = Error.InvalidOperation(description);
- }
-
- if (failure == null && !WebUtil.SuccessStatusCode(statusCode))
- {
- failure = GetResponseText(getResponseStream, statusCode);
- }
-
- if (failure != null && throwOnFailure)
- {
- throw failure;
- }
-
- return failure;
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031", Justification = "Cache exception so user can examine it later")]
- internal static DataServiceClientException GetResponseText(Func<Stream> getResponseStream, HttpStatusCode statusCode)
- {
- string message = null;
- using (System.IO.Stream stream = getResponseStream())
- {
- if ((null != stream) && stream.CanRead)
- {
- message = new StreamReader(stream).ReadToEnd();
- }
- }
-
- if (String.IsNullOrEmpty(message))
- {
- message = statusCode.ToString();
- }
-
- return new DataServiceClientException(message, (int)statusCode);
- }
-
- internal void AttachIdentity(String identity, Uri selfLink, Uri editLink, object entity, string etag)
- {
- Debug.Assert(null != identity, "must have identity");
-
- this.EnsureIdentityToResource();
-
-
- EntityDescriptor resource = this.entityDescriptors[entity];
-
- this.DetachResourceIdentity(resource);
-
-
- if (resource.IsDeepInsert)
- {
- LinkDescriptor end = this.bindings[resource.GetRelatedEnd()];
- end.State = EntityStates.Unchanged;
- }
-
- resource.ETag = etag;
- resource.Identity = identity;
- resource.SelfLink = selfLink;
- resource.EditLink = editLink;
-
- resource.State = EntityStates.Unchanged;
-
-
- this.identityToDescriptor[identity] = resource;
- }
-
-
- internal void AttachLocation(object entity, string location)
- {
- Debug.Assert(null != entity, "null != entity");
- Uri editLink = new Uri(location, UriKind.Absolute);
- String identity = Util.ReferenceIdentity(editLink.ToString());
-
- this.EnsureIdentityToResource();
-
- EntityDescriptor resource = this.entityDescriptors[entity];
- this.DetachResourceIdentity(resource);
-
-
- if (resource.IsDeepInsert)
- {
- LinkDescriptor end = this.bindings[resource.GetRelatedEnd()];
- end.State = EntityStates.Unchanged;
- }
-
- resource.Identity = identity;
- resource.EditLink = editLink;
-
- this.identityToDescriptor[identity] = resource;
- }
-
-
- internal void AttachLink(object source, string sourceProperty, object target, MergeOption linkMerge)
- {
- this.EnsureRelatable(source, sourceProperty, target, EntityStates.Unchanged);
-
- LinkDescriptor existing = null;
- LinkDescriptor relation = new LinkDescriptor(source, sourceProperty, target);
- if (this.bindings.TryGetValue(relation, out existing))
- {
- switch (linkMerge)
- {
- case MergeOption.AppendOnly:
- break;
-
- case MergeOption.OverwriteChanges:
- relation = existing;
- break;
-
- case MergeOption.PreserveChanges:
- if ((EntityStates.Added == existing.State) ||
- (EntityStates.Unchanged == existing.State) ||
- (EntityStates.Modified == existing.State && null != existing.Target))
- {
- relation = existing;
- }
-
- break;
-
- case MergeOption.NoTracking:
- throw Error.InvalidOperation(Strings.Context_RelationAlreadyContained);
- }
- }
- else
- {
- bool collectionProperty = (null != ClientType.Create(source.GetType()).GetProperty(sourceProperty, false).CollectionType);
- if (collectionProperty || (null == (existing = this.DetachReferenceLink(source, sourceProperty, target, linkMerge))))
- {
- this.bindings.Add(relation, relation);
- this.IncrementChange(relation);
- }
- else if (!((MergeOption.AppendOnly == linkMerge) ||
- (MergeOption.PreserveChanges == linkMerge && EntityStates.Modified == existing.State)))
- {
-
- relation = existing;
- }
- }
-
- relation.State = EntityStates.Unchanged;
- }
-
-
- internal EntityDescriptor InternalAttachEntityDescriptor(EntityDescriptor descriptor, bool failIfDuplicated)
- {
- Debug.Assert((null != descriptor.Identity), "must have identity");
- Debug.Assert(null != descriptor.Entity && ClientType.Create(descriptor.Entity.GetType()).IsEntityType, "must be entity type to attach");
-
- this.EnsureIdentityToResource();
-
- EntityDescriptor resource;
- this.entityDescriptors.TryGetValue(descriptor.Entity, out resource);
-
- EntityDescriptor existing;
- this.identityToDescriptor.TryGetValue(descriptor.Identity, out existing);
-
- if (failIfDuplicated && (null != resource))
- {
- throw Error.InvalidOperation(Strings.Context_EntityAlreadyContained);
- }
- else if (resource != existing)
- {
- throw Error.InvalidOperation(Strings.Context_DifferentEntityAlreadyContained);
- }
- else if (null == resource)
- {
- resource = descriptor;
-
-
- this.IncrementChange(descriptor);
- this.entityDescriptors.Add(descriptor.Entity, descriptor);
- this.identityToDescriptor.Add(descriptor.Identity, descriptor);
- }
-
-
- return resource;
- }
-
- #endregion
-
- #if ASTORIA_LIGHT
-
- internal HttpWebRequest CreateRequest(Uri requestUri, string method, bool allowAnyType, string contentType, Version requestVersion, bool sendChunked)
- {
- return CreateRequest(requestUri, method, allowAnyType, contentType, requestVersion, sendChunked, HttpStack.Auto);
- }
- #endif
-
- #if !ASTORIA_LIGHT
-
-
- internal HttpWebRequest CreateRequest(Uri requestUri, string method, bool allowAnyType, string contentType, Version requestVersion, bool sendChunked)
- #else
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sendChunked", Justification = "common parameter not used in silverlight")]
- internal HttpWebRequest CreateRequest(Uri requestUri, string method, bool allowAnyType, string contentType, Version requestVersion, bool sendChunked, HttpStack httpStackArg)
- #endif
- {
- Debug.Assert(null != requestUri, "request uri is null");
- Debug.Assert(requestUri.IsAbsoluteUri, "request uri is not absolute uri");
- Debug.Assert(
- requestUri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase) ||
- requestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase),
- "request uri is not for HTTP");
-
- Debug.Assert(
- Object.ReferenceEquals(XmlConstants.HttpMethodDelete, method) ||
- Object.ReferenceEquals(XmlConstants.HttpMethodGet, method) ||
- Object.ReferenceEquals(XmlConstants.HttpMethodPost, method) ||
- Object.ReferenceEquals(XmlConstants.HttpMethodPut, method) ||
- Object.ReferenceEquals(XmlConstants.HttpMethodMerge, method),
- "unexpected http method string reference");
-
- #if !ASTORIA_LIGHT
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
- #else
- if (httpStackArg == HttpStack.Auto)
- {
- httpStackArg = this.httpStack;
- }
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri, httpStackArg);
- #endif
-
- #if !ASTORIA_LIGHT
- if (null != this.Credentials)
- {
- request.Credentials = this.Credentials;
- }
- #endif
-
- #if !ASTORIA_LIGHT
- if (0 != this.timeout)
- {
- request.Timeout = (int)Math.Min(Int32.MaxValue, new TimeSpan(0, 0, this.timeout).TotalMilliseconds);
- }
- #endif
-
- #if !ASTORIA_LIGHT
- request.KeepAlive = true;
- #endif
-
- #if !ASTORIA_LIGHT
- request.UserAgent = "Microsoft ADO.NET Data Services";
- #endif
-
- if (this.UsePostTunneling &&
- (!Object.ReferenceEquals(XmlConstants.HttpMethodPost, method)) &&
- (!Object.ReferenceEquals(XmlConstants.HttpMethodGet, method)))
- {
- request.Headers[XmlConstants.HttpXMethod] = method;
- request.Method = XmlConstants.HttpMethodPost;
- }
- else
- {
- request.Method = method;
- }
-
- if (requestVersion != null && requestVersion.Major > 0)
- {
-
- request.Headers[XmlConstants.HttpDataServiceVersion] = requestVersion.ToString() + Util.VersionSuffix;
- }
-
- request.Headers[XmlConstants.HttpMaxDataServiceVersion] = Util.MaxResponseVersion.ToString() + Util.VersionSuffix;
-
- #if !ASTORIA_LIGHT
- if (sendChunked)
- {
- request.SendChunked = true;
- }
- #endif
-
- if (this.SendingRequest != null)
- {
- System.Net.WebHeaderCollection requestHeaders;
- #if !ASTORIA_LIGHT
- requestHeaders = request.Headers;
- SendingRequestEventArgs args = new SendingRequestEventArgs(request, requestHeaders);
- #else
- requestHeaders = request.CreateEmptyWebHeaderCollection();
- SendingRequestEventArgs args = new SendingRequestEventArgs(null, requestHeaders);
- #endif
- this.SendingRequest(this, args);
-
- #if !ASTORIA_LIGHT
- if (!Object.ReferenceEquals(args.Request, request))
- {
- request = (System.Net.HttpWebRequest)args.Request;
- }
- #else
-
- foreach (string key in requestHeaders.AllKeys)
- {
- request.Headers[key] = requestHeaders[key];
- }
- #endif
- }
-
- request.Accept = allowAnyType ?
- XmlConstants.MimeAny :
- (XmlConstants.MimeApplicationAtom + "," + XmlConstants.MimeApplicationXml);
-
- request.Headers[HttpRequestHeader.AcceptCharset] = XmlConstants.Utf8Encoding;
-
- #if !ASTORIA_LIGHT
- bool allowStreamBuffering = false;
- bool removeXMethod = true;
- #endif
-
- if (!Object.ReferenceEquals(XmlConstants.HttpMethodGet, method))
- {
- Debug.Assert(!String.IsNullOrEmpty(contentType), "Content-Type must be specified for non get operation");
- request.ContentType = contentType;
- if (Object.ReferenceEquals(XmlConstants.HttpMethodDelete, method))
- {
- request.ContentLength = 0;
- }
- #if !ASTORIA_LIGHT
- // else
- {
- allowStreamBuffering = true;
- }
- #endif
-
- if (this.UsePostTunneling && (!Object.ReferenceEquals(XmlConstants.HttpMethodPost, method)))
- {
- request.Headers[XmlConstants.HttpXMethod] = method;
- method = XmlConstants.HttpMethodPost;
- #if !ASTORIA_LIGHT
- removeXMethod = false;
- #endif
- }
- }
- else
- {
- Debug.Assert(contentType == null, "Content-Type for get methods should be null");
- }
-
- #if !ASTORIA_LIGHT
- request.AllowWriteStreamBuffering = allowStreamBuffering;
- #endif
-
- ICollection<string> headers;
- headers = request.Headers.AllKeys;
-
- #if !ASTORIA_LIGHT
- if (headers.Contains(XmlConstants.HttpRequestIfMatch))
- {
- request.Headers.Remove(HttpRequestHeader.IfMatch);
- }
- #endif
-
- #if !ASTORIA_LIGHT
- if (removeXMethod && headers.Contains(XmlConstants.HttpXMethod))
- {
- request.Head…
Large files files are truncated, but you can click here to view the full file