Esempio n. 1
0
        /// <summary>
        /// Builds the <b>Odata</b> <i>update</i> request for the entity.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="value">The value to create.</param>
        /// <returns>The <see cref="HttpRequestMessage"/>.</returns>
        internal async Task <HttpRequestMessage> BuildUpdateRequestAsync <T>(ODataArgs saveArgs, T value)
        {
            if (saveArgs == null)
            {
                throw new ArgumentNullException(nameof(saveArgs));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            var request = CreateRequestMessage(saveArgs, DetermineHttpMethod("PATCH", UpdateHttpMethod, saveArgs), saveArgs.Mapper.ODataEntityName, saveArgs.Mapper.GetKeyUrl(value));

            SetIfMatchCondition(request, saveArgs, value);

            var json = saveArgs.Mapper.MapToOData(value, Mapper.OperationTypes.Update);

            using (var ms = new StringWriter())
                using (var jw = new JsonTextWriter(ms)
                {
                    Formatting = Formatting.None
                })
                {
                    await json.WriteToAsync(jw);

                    request.Content = new StringContent(ms.ToString(), null, "application/json");
                }

            return(request);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the entity for the specified <paramref name="keys"/> (mapping from <typeparamref name="TModel"/> to <typeparamref name="T"/>) asynchronously.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The OData model <see cref="Type"/>.</typeparam>
        /// <param name="getArgs">The <see cref="ODataArgs{T, TModel}"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The entity value where found; otherwise, <c>null</c>.</returns>
        public async Task <T?> GetAsync <T, TModel>(ODataArgs <T, TModel> getArgs, params IComparable?[] keys) where T : class, new() where TModel : class, new()
        {
            if (getArgs == null)
            {
                throw new ArgumentNullException(nameof(getArgs));
            }

            var okeys = getArgs.GetODataKeys(keys);

            return(await ODataInvoker.Default.InvokeAsync(this, async() =>
            {
                try
                {
                    var val = await Client.For <TModel>(getArgs.CollectionName).Key(okeys).FindEntryAsync().ConfigureAwait(false);
                    return GetValue(getArgs, val);
                }
                catch (WebRequestException odex)
                {
                    if (odex.Code == System.Net.HttpStatusCode.NotFound && getArgs.NullOnNotFoundResponse)
                    {
                        return null;
                    }

                    throw;
                }
            }, this).ConfigureAwait(false));
        }
Esempio n. 3
0
        /// <summary>
        /// Builds the <b>Odata</b> <i>execute</i> request for the entity.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <param name="value">The value to create.</param>
        /// <returns>The <see cref="HttpRequestMessage"/>.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        internal async Task <HttpRequestMessage> BuildExecuteRequestAsync <T>(ODataArgs exeArgs, string pathAndQuery, T value)
        {
            if (exeArgs == null)
            {
                throw new ArgumentNullException(nameof(exeArgs));
            }

            var request = CreateRequestMessage(exeArgs, DetermineHttpMethod("POST", CreateHttpMethod, exeArgs), exeArgs.Mapper.ODataEntityName, null);

            request.Headers.IfMatch.Add(EntityTagHeaderValue.Any);

            if (value != null)
            {
                var json = exeArgs.Mapper.MapToOData(value, Mapper.OperationTypes.Any);

                using (var ms = new StringWriter())
                    using (var jw = new JsonTextWriter(ms)
                    {
                        AutoCompleteOnClose = true
                    })
                    {
                        await json.WriteToAsync(jw);

                        request.Content = new StringContent(ms.ToString(), null, "application/json");
                    }
            }

            return(request);
        }
Esempio n. 4
0
        /// <summary>
        /// Batches an <b>execute</b> of an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> with a <typeparamref name="TReq"/> request and <typeparamref name="TRes"/> response value.
        /// </summary>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <param name="value">The request value.</param>
        /// <returns>The <see cref="ODataBatchItem"/>.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        public async Task <ODataBatchItem> ExecuteAsync <TReq, TRes>(ODataArgs exeArgs, string pathAndQuery, TReq value)
        {
            var obi = AddRequest(await OData.BuildExecuteRequestAsync(exeArgs, pathAndQuery, value).ConfigureAwait(false));

            obi.GetValueFunc = async() => await OData.ProcessExecuteResponseAsync <TRes>(obi.ResponseMessage, exeArgs).ConfigureAwait(false);

            return(obi);
        }
Esempio n. 5
0
        /// <summary>
        /// Batches a <b>Get</b> of an <b>OData</b> entity for the specified <paramref name="keys"/>.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="getArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The <see cref="ODataBatchItem"/>.</returns>
        public async Task <ODataBatchItem> GetAsync <T>(ODataArgs getArgs, params IComparable[] keys) where T : class, new()
        {
            var obi = AddRequest(await OData.BuildGetRequestAsync(OData.SetUpArgs <T>(getArgs), keys).ConfigureAwait(false));

            obi.GetValueFunc = async() => await OData.ProcessGetResponseAsync <T>(obi.ResponseMessage, getArgs).ConfigureAwait(false);

            return(obi);
        }
Esempio n. 6
0
        /// <summary>
        /// Creates and executes a select query creating a resultant collection.
        /// </summary>
        /// <typeparam name="TColl">The collection <see cref="Type"/>.</typeparam>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="query">An optional function to enable in-place query selection.</param>
        /// <returns>A resultant collection.</returns>
        public async Task <TColl> SelectQueryAsync <TColl, T>(ODataArgs queryArgs, Func <IQueryable <T>, IQueryable <T> > query = null) where TColl : ICollection <T>, new() where T : class
        {
            var coll = new TColl();

            await SelectQueryAsync(queryArgs, coll, query);

            return(coll);
        }
Esempio n. 7
0
        /// <summary>
        /// Batches an <b>execute</b> of an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> using a <see cref="JObject"/> for the request and response.
        /// </summary>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <param name="json">Optional JSON request content.</param>
        /// <returns>The <see cref="ODataBatchItem"/>.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        public async Task <ODataBatchItem> ExecuteAsync(ODataArgs exeArgs, string pathAndQuery, JObject json)
        {
            var obi = AddRequest(await OData.BuildExecuteRequestAsync(exeArgs, pathAndQuery, json));

            obi.GetValueFunc = async() => await OData.ProcessExecuteResponseAsync(obi.ResponseMessage, exeArgs);

            return(obi);
        }
Esempio n. 8
0
 /// <summary>
 /// Gets the <b>Odata</b> entity for the specified <paramref name="keys"/> mapping to <typeparamref name="T"/>.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="getArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="keys">The key values.</param>
 /// <returns>The entity value where found; otherwise, <c>null</c>.</returns>
 public async Task <T> GetAsync <T>(ODataArgs getArgs, params IComparable[] keys) where T : class, new()
 {
     return(await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildGetRequestAsync(SetUpArgs <T>(getArgs), keys);
         OnCreatingRequest(request);
         var response = await SendRequestAsync(request);
         getArgs.ResponseMessage = response;
         return await ProcessGetResponseAsync <T>(response, getArgs);
     }, this));
 }
Esempio n. 9
0
 /// <summary>
 /// Invoke the GET query using the <paramref name="queryAggregator"/> and add to the <paramref name="coll"/>.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="queryAggregator">The <see cref="ODataQueryAggregator"/>.</param>
 /// <param name="coll">The collection to add items to.</param>
 internal async Task Query <T>(ODataArgs queryArgs, ODataQueryAggregator queryAggregator, ICollection <T> coll)
 {
     await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildQueryRequestAsync(queryArgs, queryAggregator.ToString());
         OnCreatingRequest(request);
         var response = await SendRequestAsync(request);
         queryArgs.ResponseMessage = response;
         await ProcessQueryResponse(response, queryArgs, queryAggregator, coll);
     }, this);
 }
Esempio n. 10
0
 /// <summary>
 /// Executes an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> with a <typeparamref name="TReq"/> request value.
 /// </summary>
 /// <typeparam name="TReq">The request <see cref="Type"/>.</typeparam>
 /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
 /// <param name="value">The request value.</param>
 /// <returns>The <see cref="Task"/> with no response value.</returns>
 /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
 public async Task ExecuteAsync <TReq>(ODataArgs exeArgs, string pathAndQuery, TReq value)
 {
     await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildExecuteRequestAsync <TReq>(exeArgs, pathAndQuery, value);
         OnCreatingRequest(request);
         var response            = await SendRequestAsync(request);
         exeArgs.ResponseMessage = response;
         EnsureSuccessStatusCodeForResponse(response);
     }, this);
 }
Esempio n. 11
0
        /// <summary>
        /// Executes an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> with a <typeparamref name="TRes"/> response.
        /// </summary>
        /// <typeparam name="TRes">The response <see cref="Type"/>.</typeparam>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <returns>The resulting value.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        public async Task <TRes> ExecuteAsync <TRes>(ODataArgs exeArgs, string pathAndQuery)
        {
            var json = await ExecuteAsync(exeArgs, pathAndQuery, null);

            if (json == null)
            {
                return(default(TRes));
            }

            return((TRes)exeArgs.Mapper.MapFromOData(json, Mapper.OperationTypes.Any));
        }
Esempio n. 12
0
 /// <summary>
 /// Deletes (<see cref="DeleteHttpMethod"/>) the <b>Odata</b> entity for the specified <paramref name="keys"/>.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="keys">The key values.</param>
 public async Task DeleteAsync <T>(ODataArgs saveArgs, params IComparable[] keys) where T : class, new()
 {
     await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildDeleteRequestAsync(SetUpArgs <T>(saveArgs), keys);
         OnCreatingRequest(request);
         var response             = await SendRequestAsync(request);
         saveArgs.ResponseMessage = response;
         EnsureSuccessStatusCodeForResponse(response);
     }, this);
 }
Esempio n. 13
0
 /// <summary>
 /// Executes an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> using a <see cref="JObject"/> for the request and response.
 /// </summary>
 /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
 /// <param name="json">Optional JSON request content.</param>
 /// <returns>The resulting <see cref="JObject"/>.</returns>
 /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
 public async Task <JObject> ExecuteAsync(ODataArgs exeArgs, string pathAndQuery, JObject json)
 {
     return(await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildExecuteRequestAsync(exeArgs, pathAndQuery, json);
         OnCreatingRequest(request);
         var response = await SendRequestAsync(request);
         exeArgs.ResponseMessage = response;
         return await ProcessExecuteResponseAsync(response, exeArgs);
     }, this));
 }
Esempio n. 14
0
        /// <summary>
        /// Executes an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> with a <typeparamref name="TRes"/> response.
        /// </summary>
        /// <typeparam name="TRes">The response <see cref="Type"/>.</typeparam>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <returns>The resulting value.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        public async Task <TRes> ExecuteAsync <TRes>(ODataArgs exeArgs, string pathAndQuery)
        {
            if (exeArgs == null)
            {
                throw new ArgumentNullException(nameof(exeArgs));
            }

            var json = await ExecuteAsync(exeArgs, pathAndQuery, null).ConfigureAwait(false);

            if (json == null)
            {
                return(default);
Esempio n. 15
0
 /// <summary>
 /// Updates (<see cref="UpdateHttpMethod"/>) the <b>Odata</b> entity.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="value">The value to create.</param>
 /// <returns>The value (re-queried where specified).</returns>
 public async Task <T> UpdateAsync <T>(ODataArgs saveArgs, T value) where T : class, new()
 {
     return(await ODataInvoker.Default.InvokeAsync(this, async() =>
     {
         var request = await BuildUpdateRequestAsync <T>(SetUpArgs <T>(saveArgs), value);
         OnCreatingRequest(request);
         var response = await SendRequestAsync(request);
         saveArgs.ResponseMessage = response;
         EnsureSuccessStatusCodeForResponse(response);
         return value;
     }, this));
 }
Esempio n. 16
0
        /// <summary>
        /// Processes the <b>Odata</b> <i>query</i> <see cref="HttpResponseMessage"/>.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="response">The <see cref="HttpResponseMessage"/>.</param>
        /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="queryAggregator">The <see cref="ODataQueryAggregator"/>.</param>
        /// <param name="coll">The collection to add to.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        internal async Task ProcessQueryResponse <T>(HttpResponseMessage response, ODataArgs queryArgs, ODataQueryAggregator queryAggregator, ICollection <T> coll)
        {
            EnsureSuccessStatusCodeForResponse(response);

            var          type   = typeof(T);
            IODataMapper mapper = null;
            PropertyInfo pi     = null;

            switch (queryAggregator.SelectClause.Selector.NodeType)
            {
            case System.Linq.Expressions.ExpressionType.MemberAccess:
                mapper = queryArgs.Mapper;
                var me = (System.Linq.Expressions.MemberExpression)queryAggregator.SelectClause.Selector;
                pi = (PropertyInfo)me.Member;
                break;

            default:
                mapper = queryArgs.Mapper.SrceType == type ? queryArgs.Mapper : ODataAutoMapper.GetMapper(type);
                break;
            }

            int?count = null;

            using (var s = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                using (var sr = new StreamReader(s))
                    using (var jr = new JsonTextReader(sr))
                    {
                        var json = await JObject.LoadAsync(jr).ConfigureAwait(false);

                        count = json.Value <int?>("@odata.count");

                        foreach (var jt in json.GetValue("value"))
                        {
                            var obj = mapper.MapFromOData(jt, Mapper.OperationTypes.Get);
                            if (pi == null)
                            {
                                coll.Add((T)obj);
                            }
                            else
                            {
                                coll.Add((T)pi.GetValue(obj));
                            }
                        }
                    }

            if (count.HasValue && queryArgs.Paging != null && queryArgs.Paging.IsGetCount)
            {
                queryArgs.Paging.TotalCount = count.Value;
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Builds the <b>Odata</b> <i>delete</i> request for the specified <paramref name="keys"/>.
        /// </summary>
        /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The <see cref="HttpRequestMessage"/>.</returns>
        internal async Task <HttpRequestMessage> BuildDeleteRequestAsync(ODataArgs saveArgs, params IComparable[] keys)
        {
            if (saveArgs == null)
            {
                throw new ArgumentNullException(nameof(saveArgs));
            }

            if (keys == null || keys.Length == 0)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            return(await Task.FromResult(CreateRequestMessage(saveArgs, DetermineHttpMethod("DELETE", DeleteHttpMethod, saveArgs), saveArgs.Mapper.ODataEntityName, saveArgs.Mapper.GetKeyUrl(keys))));
        }
Esempio n. 18
0
        /// <summary>
        /// Gets the model.
        /// </summary>
        private async Task <TModel?> GetModelAsync <T, TModel>(ODataArgs <T, TModel> getArgs, object[]?keys) where T : class, new() where TModel : class, new()
        {
            try
            {
                return(await Client.For <TModel>(getArgs.CollectionName).Key(keys).FindEntryAsync().ConfigureAwait(false));
            }
            catch (WebRequestException odex)
            {
                if (odex.Code == System.Net.HttpStatusCode.NotFound && getArgs.NullOnNotFoundResponse)
                {
                    return(null);
                }

                throw;
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Builds the <b>Odata</b> <i>get</i> request for the specified <paramref name="keys"/>.
        /// </summary>
        /// <param name="args">The <see cref="ODataArgs"/>.</param>
        /// <param name="keys">The key values.</param>
        /// <returns>The <see cref="HttpRequestMessage"/>.</returns>
        internal async Task <HttpRequestMessage> BuildGetRequestAsync(ODataArgs args, params IComparable[] keys)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            if (keys == null || keys.Length == 0)
            {
                throw new ArgumentNullException(nameof(keys));
            }

            string q = $"{args.Mapper.GetKeyUrl(keys)}?{args.GetODataQuery()}";

            return(await Task.FromResult(CreateRequestMessage(args, DetermineHttpMethod("GET", GetHttpMethod, args), args.Mapper.ODataEntityName, q)));
        }
Esempio n. 20
0
        /// <summary>
        /// Sets up (creates) and auto-maps the <paramref name="args"/>.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/>.</typeparam>
        /// <param name="args">The <see cref="ODataArgs"/>.</param>
        /// <returns>An updated or created <see cref="ODataArgs"/>.</returns>
        internal ODataArgs SetUpArgs <T>(ODataArgs args)
        {
            var oa = args ?? new ODataArgs();

            if (oa.Mapper == null)
            {
                oa.Mapper = ODataAutoMapper.GetMapper(typeof(T));
            }
            else if (oa.Mapper.SrceType != typeof(T))
            {
                throw new ArgumentException($"The Entity Type is '{typeof(T).Name}' and the Mapper Type is '{oa.Mapper.SrceType.Name}'; these must be the same.");
            }

            args = oa;
            return(args);
        }
Esempio n. 21
0
        /// <summary>
        /// Creates and executes a select query adding to the passed collection.
        /// </summary>
        /// <typeparam name="TColl">The collection <see cref="Type"/>.</typeparam>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="coll">The collection to add items to.</param>
        /// <param name="query">An optional function to enable in-place query selection.</param>
        public Task SelectQueryAsync <TColl, T>(ODataArgs queryArgs, TColl coll, Func <IQueryable <T>, IQueryable <T> > query = null) where TColl : ICollection <T> where T : class
        {
            var q = CreateQuery <T>(queryArgs);

            if (query != null)
            {
                var q2 = query(q) as ODataQueryable <T>;
                q = q2 ?? throw new InvalidOperationException("The query function must return an instance of OdmQueryable<T>.");
            }

            return(Task.Run(() =>
            {
                foreach (var item in q.AsEnumerable())
                {
                    coll.Add(item);
                }
            }));
        }
Esempio n. 22
0
        /// <summary>
        /// Creates the entity (mapping from <typeparamref name="T"/> to <typeparamref name="TModel"/>) asynchronously.
        /// </summary>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <typeparam name="TModel">The OData model <see cref="Type"/>.</typeparam>
        /// <param name="saveArgs">The <see cref="ODataArgs{T, TModel}"/>.</param>
        /// <param name="value">The value to create.</param>
        /// <returns>The created entity value.</returns>
        public async Task <T> CreateAsync <T, TModel>(ODataArgs <T, TModel> saveArgs, T value) where T : class, new() where TModel : class, new()
        {
            if (saveArgs == null)
            {
                throw new ArgumentNullException(nameof(saveArgs));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            // Note: ChangeLog is not updated (if it exists) as it is assumed the OData data source is responsible for this.

            return(await ODataInvoker.Default.InvokeAsync(this, async() =>
            {
                var model = saveArgs.Mapper.MapToDest(value, Mapper.OperationTypes.Create) ?? throw new InvalidOperationException("Mapping to the OData model must not result in a null value.");
                var created = await Client.For <TModel>(saveArgs.CollectionName).Set(model).InsertEntryAsync(true).ConfigureAwait(false);
                return GetValue(saveArgs, created);
            }, this).ConfigureAwait(false));
Esempio n. 23
0
        /// <summary>
        /// Builds the <b>Odata</b> <i>execute</i> request.
        /// </summary>
        /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
        /// <param name="json">Optional JSON request content.</param>
        /// <returns>The <see cref="HttpRequestMessage"/>.</returns>
        /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
        internal async Task <HttpRequestMessage> BuildExecuteRequestAsync(ODataArgs exeArgs, string pathAndQuery, JObject json = null)
        {
            if (exeArgs == null)
            {
                throw new ArgumentNullException(nameof(exeArgs));
            }

            if (string.IsNullOrEmpty(pathAndQuery))
            {
                throw new ArgumentNullException(nameof(pathAndQuery));
            }

            var request = CreateRequestMessage(exeArgs, DetermineHttpMethod("POST", null, exeArgs), null, pathAndQuery);

            if (json != null)
            {
                request.Content = new StringContent(json.ToString(), null, "application/json");
            }

            return(await Task.FromResult(request));
        }
Esempio n. 24
0
        /// <summary>
        /// Creates (<see cref="ODataBase.CreateQuery{T}(ODataArgs)"/>) and batches a <b>Select query</b> for the <b>OData</b> entity.
        /// </summary>
        /// <typeparam name="TColl">The collection <see cref="Type"/>.</typeparam>
        /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
        /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
        /// <param name="query">An optional function to enable in-place query selection.</param>
        /// <returns>The <see cref="ODataBatchItem"/>.</returns>
        public async Task <ODataBatchItem> SelectQueryAsync <TColl, T>(ODataArgs queryArgs, Func <IQueryable <T>, IQueryable <T> > query = null) where TColl : ICollection <T>, new() where T : class
        {
            var q = OData.CreateQuery <T>(queryArgs);

            if (query != null)
            {
                var q2 = query(q) as ODataQueryable <T>;
                q = q2 ?? throw new InvalidOperationException("The query function must return an instance of ODataQueryable<T>.");
            }

            var qa  = q.QueryExecutor.GetQueryAggregator(q.Expression, null);
            var obi = AddRequest(await OData.BuildQueryRequestAsync(queryArgs, qa.ToString()).ConfigureAwait(false));

            obi.GetValueFunc = async() =>
            {
                var coll = new TColl();
                await OData.ProcessQueryResponse(obi.ResponseMessage, queryArgs, qa, coll).ConfigureAwait(false);

                return(coll);
            };

            return(obi);
        }
Esempio n. 25
0
        /// <summary>
        /// Sets the IF-MATCH condition for the eTag.
        /// </summary>
        private static void SetIfMatchCondition(HttpRequestMessage request, ODataArgs args, object value)
        {
            if (value == null)
            {
                return;
            }

            switch (args.IfMatch)
            {
            case ODataIfMatch.UpdateEtag:
                if (!(value is IETag etag))
                {
                    goto case ODataIfMatch.UpdateAny;
                }

                request.Headers.IfMatch.Add(new EntityTagHeaderValue(etag.ETag));
                break;

            case ODataIfMatch.UpdateAny:
                request.Headers.IfMatch.Add(EntityTagHeaderValue.Any);
                break;
            }
        }
Esempio n. 26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ODataQueryable{T}"/> class.
 /// </summary>
 /// <param name="odata">The <see cref="ODataBase"/>.</param>
 /// <param name="queryArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="executor">The <see cref="IQueryExecutor"/>.</param>
 public ODataQueryable(ODataBase odata, ODataArgs queryArgs, ref IQueryExecutor executor)
     : base(QueryParser.CreateDefault(), CreateExecutor(odata, queryArgs, ref executor))
 {
     QueryExecutor = (ODataQueryExecutor)executor;
 }
Esempio n. 27
0
 /// <summary>
 /// Batches an <b>execute</b> of an <b>OData</b> request for a specified <paramref name="pathAndQuery"/> with a <typeparamref name="TReq"/> request value.
 /// </summary>
 /// <param name="exeArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="pathAndQuery">The url path and query <see cref="string"/> (excluding the base URI path).</param>
 /// <param name="value">The request value.</param>
 /// <returns>The <see cref="ODataBatchItem"/>.</returns>
 /// <remarks>The <see cref="HttpMethod"/> defaults to a <see cref="HttpMethod.Post"/>. This is overridden using the <see cref="ODataArgs.OverrideHttpMethod"/>.</remarks>
 public async Task <ODataBatchItem> ExecuteAsync <TReq>(ODataArgs exeArgs, string pathAndQuery, TReq value)
 {
     return(AddRequest(await OData.BuildExecuteRequestAsync(exeArgs, pathAndQuery, value).ConfigureAwait(false)));
 }
Esempio n. 28
0
 /// <summary>
 /// Batches a <b>Delete</b> of an <b>Odata</b> entity for the specified <paramref name="keys"/>.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="keys">The key values.</param>
 /// <returns>The <see cref="ODataBatchItem"/>.</returns>
 public async Task <ODataBatchItem> DeleteAsync <T>(ODataArgs saveArgs, params IComparable[] keys) where T : class, new()
 {
     return(AddRequest(await OData.BuildDeleteRequestAsync(OData.SetUpArgs <T>(saveArgs), keys).ConfigureAwait(false)));
 }
Esempio n. 29
0
 /// <summary>
 /// Batches an <b>Update</b> of an <b>Odata</b> entity.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <param name="saveArgs">The <see cref="ODataArgs"/>.</param>
 /// <param name="value">The entity value.</param>
 /// <returns>The <see cref="ODataBatchItem"/>.</returns>
 public async Task <ODataBatchItem> UpdateAsync <T>(ODataArgs saveArgs, T value) where T : class, new()
 {
     return(AddRequest(await OData.BuildUpdateRequestAsync(OData.SetUpArgs <T>(saveArgs), value).ConfigureAwait(false)));
 }
Esempio n. 30
0
 /// <summary>
 /// Creates an <see cref="ODataQuery{T, TModel}"/> to enable select-like capabilities.
 /// </summary>
 /// <typeparam name="T">The entity <see cref="Type"/>.</typeparam>
 /// <typeparam name="TModel">The OData model <see cref="Type"/>.</typeparam>
 /// <param name="queryArgs">The <see cref="ODataArgs{T, TModel}"/>.</param>
 /// <param name="query">The function to further define the query.</param>
 /// <returns>A <see cref="ODataQuery{T, TModel}"/>.</returns>
 public ODataQuery <T, TModel> Query <T, TModel>(ODataArgs <T, TModel> queryArgs, Func <Soc.IBoundClient <TModel>, Soc.IBoundClient <TModel> >?query = null) where T : class, new() where TModel : class, new()
 {
     return(new ODataQuery <T, TModel>(this, queryArgs, query));
 }