예제 #1
0
        //public IList<CompositeSubRequest> UpsertExternal<T>(string referenceId, string objectName, string externalFieldName, IList<T> records)
        //{
        //    return UpsertExternal(referenceId, false, externalFieldName, records);
        //}

        //public IList<CompositeSubRequest> UpsertExternal<T>(string referenceId, bool allOrNone, string externalFieldName, IList<T> records)
        //{
        //    if (string.IsNullOrEmpty(referenceId)) throw new ArgumentNullException("referenceId");
        //    if (records == null || !records.Any()) throw new ArgumentNullException("records");

        //    var result = new List<CompositeSubRequest>();

        //    if (allOrNone && records.Count() > 200) throw new ArgumentOutOfRangeException("records");

        //    foreach (var (chunk, chunkIdx) in EnumerableChunk.Create(records, 200).Select((chunk, chunkIdx) => (chunk, chunkIdx)))
        //    {
        //        var bodyRecords = JToken.FromObject(chunk.Select(record => Dnf.UnFlatten(JObject.FromObject(record))));
        //        var request = new CompositeSubRequest
        //        {
        //            ResponseType = "collections",
        //            Body = new JObject
        //            {
        //                ["allOrNone"] = allOrNone,
        //                ["records"] = bodyRecords
        //            },
        //            Method = "PATCH",
        //            ReferenceId = $"{referenceId}_{chunkIdx}",
        //            Url = "composite/sobjects"
        //        };
        //        CompositeRequests.Add(request);
        //        result.Add(request);
        //    }
        //    return result;
        //}

        public IList <CompositeSubRequest> Delete(string referenceId, bool allOrNone, params string[] ids)
        {
            if (string.IsNullOrEmpty(referenceId))
            {
                throw new ArgumentNullException(nameof(referenceId));
            }
            if (ids == null || ids.Length == 0)
            {
                throw new ArgumentNullException(nameof(ids));
            }

            if (allOrNone && ids.Length > 200)
            {
                throw new ArgumentOutOfRangeException(nameof(ids));
            }

            var result = new List <CompositeSubRequest>();

            foreach (var(chunk, chunkIdx) in EnumerableChunk.Create(ids, 200).Select((chunk, chunkIdx) => (chunk, chunkIdx)))
            {
                var request = new CompositeSubRequest
                {
                    ResponseType = "collections",
                    Method       = "DELETE",
                    ReferenceId  = $"{referenceId}_{chunkIdx}",
                    Url          = $"composite/sobjects?ids={string.Join(",", chunk.Select(Uri.EscapeDataString))}{(allOrNone ? "&allOrNone=" : "")}"
                };
                CompositeRequests.Add(request);
                result.Add(request);
            }
            return(result);
        }
예제 #2
0
        public static IEnumerable <string> ChunkIds(IEnumerable <string> source, string soql, string template)
        {
            soql = soql.Trim().Replace("\r\n", "\n");
            // var soqlMaxLen = 20000;
            var nonTemplateLength = soql.Replace(template, "").Length;
            // var idsTextLen = soqlMaxLen - nonTemplateLength;
            var idsTextLen    = SoqlMaxLength - nonTemplateLength;
            var numOfTemplate = (int)Math.Ceiling((soql.Length - nonTemplateLength) / (double)template.Length);
            var numOfId       = (int)Math.Max(1, Math.Floor(idsTextLen / (18.0 * numOfTemplate)));

            return(EnumerableChunk.Create(source, numOfId)
                   .Select(l => soql.Replace(template, string.Join(",", l.Select(id => SoqlString(ToId15(id)))))));
        }
예제 #3
0
        public async IAsyncEnumerable <QueryResult <T> > QueryByLocatorAsync <T>(QueryResult <T>?queryResult, int compositeLimit)
        {
            if (queryResult == null)
            {
                yield break;
            }
            yield return(queryResult);

            // batch size can be changed via Sforce-Query-Options header
            // i.e. request.Query(referenceId, query).HttpHeaders = new HttpHeaders().QueryOptions(200);
            // https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers_queryoptions.htm
            // The default is 2,000; the minimum is 200, and the maximum is 2,000.
            // There is no guarantee that the requested batch size is the actual batch size.
            // Changes are made as necessary to maximize performance.
            if (compositeLimit > Dnf.CompositeQueryLimit)
            {
                compositeLimit = Dnf.CompositeQueryLimit;
            }
            var batchSize = GetBatchSizeByUrl(queryResult.NextRecordsUrl);
            var batches   = PredictQueryLocators(queryResult.NextRecordsUrl, queryResult.Records?.Count ?? 0,
                                                 queryResult.TotalSize - (queryResult.Records?.Count ?? 0), batchSize);
            var chunks = EnumerableChunk.Create(batches, compositeLimit);

            foreach (var(batch, _) in chunks.Select((batch, batchIdx) => (batch, batchIdx)))
            {
                //await Dnf.QueryCursorThrottler.WaitAsync().ConfigureAwait(true);
                //try
                //{
                await foreach (var chunkResult in QueryByChunkAsync <T>(batch)
                               .ConfigureAwait(false))
                {
                    // if (batchIdx > 0 && recordIdx == 0)
                    //     await tasks[batchIdx - 1].ConfigureAwait(false);
                    //queryResult.Records.Add(record);
                    //queryResult.Done = queryResult.Records.Count >= queryResult.TotalSize;
                    yield return(chunkResult);
                }
                //}
                //finally
                //{
                //    Dnf.QueryCursorThrottler.Release();
                //}
            }
        }
예제 #4
0
        public IList <CompositeSubRequest> RetrieveExternal(string referenceId, string objectName, string externalFieldName, IList <string> externalIds, params string[] fields)
        {
            if (string.IsNullOrEmpty(referenceId))
            {
                throw new ArgumentNullException(nameof(referenceId));
            }
            if (string.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (string.IsNullOrEmpty(externalFieldName))
            {
                throw new ArgumentNullException(nameof(externalFieldName));
            }
            if (externalIds == null || !externalIds.Any())
            {
                throw new ArgumentNullException(nameof(externalIds));
            }
            if (fields == null || fields.Length == 0)
            {
                throw new ArgumentNullException(nameof(fields));
            }

            var result = new List <CompositeSubRequest>();

            foreach (var(chunk, chunkIdx) in EnumerableChunk.Create(externalIds, 2000).Select((chunk, chunkIdx) => (chunk, chunkIdx)))
            {
                var request = new CompositeSubRequest
                {
                    ResponseType = "collections",
                    Body         = new JObject
                    {
                        ["ids"]    = JToken.FromObject(chunk.Select(id => id)),
                        ["fields"] = JToken.FromObject(fields)
                    },
                    Method      = "POST",
                    ReferenceId = $"{referenceId}_{chunkIdx}",
                    Url         = $"composite/sobjects/{objectName}/{externalFieldName}"
                };
                CompositeRequests.Add(request);
                result.Add(request);
            }
            return(result);
        }
예제 #5
0
        public IList <CompositeSubRequest> Create <T>(string referenceId, bool allOrNone, IList <T> records)
        {
            if (string.IsNullOrEmpty(referenceId))
            {
                throw new ArgumentNullException(nameof(referenceId));
            }
            if (records == null || !records.Any())
            {
                throw new ArgumentNullException(nameof(records));
            }

            if (allOrNone && records.Count > 200)
            {
                throw new ArgumentOutOfRangeException(nameof(records));
            }

            var result = new List <CompositeSubRequest>();

            foreach (var(chunk, chunkIdx) in EnumerableChunk.Create(records, 200).Select((chunk, chunkIdx) => (chunk, chunkIdx)))
            {
                var bodyRecords = JToken.FromObject(chunk.Select(record => record == null ? new JObject() : Dnf.UnFlatten(JObject.FromObject(record))));
                var request     = new CompositeSubRequest
                {
                    ResponseType = "collections",
                    Body         = new JObject
                    {
                        ["allOrNone"] = allOrNone,
                        ["records"]   = bodyRecords
                    },
                    Method      = "POST",
                    ReferenceId = $"{referenceId}_{chunkIdx}",
                    Url         = "composite/sobjects"
                };
                CompositeRequests.Add(request);
                result.Add(request);
            }
            return(result);
        }
예제 #6
0
 public static string?EscapeDataString(string?uri)
 {
     return(uri == null ? null : string.Join("", EnumerableChunk.Create(uri, 65519).Select(c => Uri.EscapeDataString(new string(c.ToArray())))));
 }