使用多个同步 Xmlhttprequests 到 Create/Update Microsoft Dynamics CRM 订单详细记录不工作

Using Multple Asyncronous Xmlhttprequests to Create/Update Microsoft Dynamics CRM Order Detail Records Not Working

我正在尝试使用 oData 端点发送多个异步 xmlhttprequest。其中一些正在创建订单详细信息并正在更新 Microsoft Dynamics CRM 2013 中的订单详细信息。

如果我使用开发人员工具并手动跟踪代码,它工作正常。但是,如果我 运行 它来自我的网络资源,我会不断从服务器收到 500 条响应。一些请求正确完成,而其他请求失败。

我正在寻找一个纯粹的 javascript 解决方案。我试过谷歌搜索并查看了 Whosebug 上的多个帖子,但无济于事。我使用过 Fiddler2,但响应文本是 'Generic SQL Error'。如果我在 composer 中再次 运行 请求,它就可以正常工作。可能是数据库锁定问题吗?

在此先感谢,如果需要我可以提供更多信息。

这是我的 for 循环代码:

var updateDetails = function (data) {
    var table = document.getElementById("selectedItemTable");
    var tbody = table.getElementsByTagName("tbody")[0];
    var upsaleQty, qty;
    var salesOrderDetailId;

    for (var i = 0; i < tbody.childElementCount; i++) {
        var prodName = tbody.rows[i].cells[0].innerHTML;
        var match = false;

        for (var j = 0; j < data.length; j++) {
            if (prodName === data[j].product_order_details.tf_ShortName) {
                match = true;
                upsaleQty = data[j].tf_UpsaleQty ? parseFloat(data[j].tf_UpsaleQty) : 0;
                qty = parseFloat(data[j].Quantity) + parseFloat(tbody.rows[i].cells[1].innerHTML);
                salesOrderDetailId = data[j].SalesOrderDetailId;
            }
        }

        if (!match) {
            var productQuery = odataBaseUrl + "/ProductSet?$filter=tf_ShortName eq '" + prodName + "'&$select=Name,tf_ShortName,ProductId,DefaultUoMId";
            performRequest(productQuery, createDetail);
        } else {
            upsaleQty = upsaleQty + parseFloat(tbody.rows[i].cells[1].innerHTML);

            // Update Order Detail
            var updateObj = {};
            updateObj.tf_UpsaleQty = upsaleQty.toFixed(5);
            updateObj.Quantity = qty.toFixed(5);

            var updateDetail = JSON.stringify(updateObj);

            console.dir("Update " + prodName + ":" + updateDetail);

            createUpdateDetail(true, salesOrderDetailId, updateDetail);
        }
    }

    makePdf();
    document.getElementById("save").style.visibility = "hidden";
}

这是发送 create/update 请求的代码:

var createUpdateDetail = function (update, orderDetailGuid, json) {
    var odataReq = odataBaseUrl + "/SalesOrderDetailSet";

    if (update) {
        odataReq += "(guid'" + orderDetailGuid + "')";
    }

    var oReq = getXMLHttpRequest();

    if (oReq != null) {
        oReq.open("POST", encodeURI(odataReq), true);
        oReq.setRequestHeader("Accept", "application/json");
        oReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");

        if (update) {
            oReq.setRequestHeader("X-HTTP-Method", "MERGE");
        }

        oReq.send(json);
    } else {
        alert('Error in creating request.');
    }
}

这里是执行请求函数:

var performRequest = function (odataUrl, onReadyFunction, concatResults) {
    console.dir(odataUrl);

    var oReq = getXMLHttpRequest();
    if (oReq != null) {
        oReq.open("GET", encodeURI(odataUrl), true);
        oReq.setRequestHeader("Accept", "application/json");
        oReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        oReq.onreadystatechange = function () {
            if (oReq.readyState == 4 && oReq.status == 200) {
                // Parse the result

                if (!concatResults) {
                    concatResults = new Object();
                    concatResults.results = new Array();
                }

                oReq.onreadystatechange = null; //avoids memory leaks
                console.dir(oReq.responseText);
                var result = window.JSON.parse(oReq.responseText).d;

                for (var i = 0; i < result.results.length; i++) {
                    concatResults.results.push(result.results[i])
                }

                if (result.__next != null)
                    performRequest(decodeURI(result.__next), onReadyFunction, concatResults);
                else
                    onReadyFunction(concatResults.results);
            }
        };
        oReq.send();
    } else {
        alert('Error in creating request.');
    }

}

创建详细信息函数:

var createDetail = function (data) {
    // Create Order Detail
    var table = document.getElementById("selectedItemTable");
    var tbody = table.getElementsByTagName("tbody")[0];
    var qty = 0;

    for (var i = 0; i < tbody.childElementCount; i++) {
        if (data[0].tf_ShortName === tbody.rows[i].cells[0].innerHTML) {
            qty = parseFloat(tbody.rows[i].cells[1].innerHTML).toFixed(5);
        }
    }

    var createObj = {};
    createObj.SalesOrderId = { Id: orderGuid, LogicalName: "salesorder" };
    createObj.ProductId = { Id: data[0].ProductId, LogicalName: "product" };
    createObj.Quantity = qty;
    createObj.tf_UpsaleQty = qty;
    createObj.UoMId = { Id: data[0].DefaultUoMId.Id, LogicalName: data[0].DefaultUoMId.LogicalName };
    var createDet = JSON.stringify(createObj);

    console.dir("Create:" + createDet);

    createUpdateDetail(false, "", createDet);
}

我认为 ExecuteMultipleRequest 到 SOAP 端点,这是您的解决方案。因此,您只会收到一次服务调用,而不是进行当前在您的解决方案中实现的多次服务调用。

如果您避免在代码中生成请求字符串到 soap 端点,我想向您推荐 this JS 库。

我最终创建了一个数组并将其视为一个队列。我将所有用于创建和更新订单详细信息的 odata 请求放入数组中,然后按顺序处理它们。 onreadystatechange 将触发下一个请求。诚然,它的效率不如 运行 并行处理,但它可以满足我的需要并解决了 500 个错误。感谢您的帮助。