首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Quickbooks导入

Quickbooks导入
EN

Stack Overflow用户
提问于 2017-01-27 02:28:57
回答 2查看 231关注 0票数 0

我正在使用Consoli字节提供的出色的Quickbooks,并将销售代表导入到数据库中。下面的代码是请求xml的代码。Quickbook文件有3000多个销售代表,响应xml无效。我知道我可以使用metaData获取计数,并使用MaxReturned获取有限的记录。不确定迭代器中是否有?

我将xml传递给mssql数据库并在那里解析它。问题是当xml无效时,它会导致sqlserver挂起,因为查询正在运行,所以在将xml传递给sql之前,我需要验证xml。

任何帮助都将不胜感激。

代码语言:javascript
复制
$xml = '<?xml version="1.0" encoding="utf-8"?>
            <?qbxml version="' . $version . '"?>
            <QBXML>
                <QBXMLMsgsRq onError="stopOnError">
                    <SalesRepQueryRq>
                        <ActiveStatus>ActiveOnly</ActiveStatus>
                        <FromModifiedDate>' . $last . '</FromModifiedDate>
                        <IncludeRetElement>ListID</IncludeRetElement>
                        <IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
                    </SalesRepQueryRq>
                </QBXMLMsgsRq>
            </QBXML>';

    return $xml;

--用下面的代码更新-- @keith --谢谢你花时间回复。下面是我对请求/响应功能的看法

代码语言:javascript
复制
   //sales rep list import request
function _quickbooks_salesrep_import_request($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $version, $locale)
{
    $last = _quickbooks_get_last_run($user, $action); //get last run time
    _quickbooks_set_last_run($user, $action); //set current run

    // Build the request
    $xml = '<?xml version="1.0" encoding="utf-8"?>
            <?qbxml version="' . $version . '"?>
            <QBXML>
                <QBXMLMsgsRq onError="stopOnError">
                    <SalesRepQueryRq>
                        <ActiveStatus>ActiveOnly</ActiveStatus>
                        <FromModifiedDate>' . $last . '</FromModifiedDate>
                        <IncludeRetElement>ListID</IncludeRetElement>
                        <IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
                    </SalesRepQueryRq>
                </QBXMLMsgsRq>
            </QBXML>';

    return $xml;
}

//sales rep list import response
function _quickbooks_salesrep_import_response ($requestID, $user, $action, $ID, $extra, &$err, $last_action_time, $last_actionident_time, $xml, $idents)
{
      global $conn;
      $sql = '{call dbo.spQBAddUpdateSalesRep (?)}';
      $params = array($xml);
      $stmt = dbQuery($sql,$conn,$params);
      dbCloseQuery($stmt);
    //QuickBooks_Utilities::log(QB_QUICKBOOKS_DSN, 'rep xml - ' . $xml);
    return true;
}

下面是我传递xml的存储过程中的内容

代码语言:javascript
复制
@strXML XML --- this is passed as parameter

BEGIN TRY
BEGIN TRANSACTION

UPDATE dbo.qb_salesrep SET
             TimeCreated = SUB.TimeCreated
            ,TimeModified = SUB.TimeModified
            ,EditSequence = SUB.EditSequence
            ,Initial = SUB.Initial
            ,IsActive = SUB.IsActive
            ,SalesRepEntityRef_ListID = SUB.SalesRepEntityRef_ListID
            ,SalesRepEntityRef_FullName = SUB.SalesRepEntityRef_FullName
        FROM
            (SELECT
                 ListID = x.c.value('ListID[1]','VARCHAR(36)')
                ,TimeCreated = x.c.value('TimeCreated[1]','DATETIME')
                ,TimeModified = x.c.value('TimeModified[1]','DATETIME')
                ,EditSequence = x.c.value('EditSequence[1]','VARCHAR(16)')
                ,Initial = x.c.value('Initial[1]','VARCHAR(5)')
                ,IsActive = x.c.value('IsActive[1]','BIT')
                ,SalesRepEntityRef_ListID = x.c.value('SalesRepEntityRef[1]/ListID[1]','VARCHAR(36)')
                ,SalesRepEntityRef_FullName = x.c.value('SalesRepEntityRef[1]/FullName[1]','VARCHAR(41)')
            FROM
                @strXML.nodes('QBXML/QBXMLMsgsRs/SalesRepQueryRs/SalesRepRet') x(c)) AS SUB
        WHERE
            dbo.qb_salesrep.ListID = SUB.ListID 

INSERT INTO dbo.qb_salesrep (
                 ListID
                ,TimeCreated
                ,TimeModified
                ,EditSequence
                ,Initial
                ,IsActive
                ,SalesRepEntityRef_ListID
                ,SalesRepEntityRef_FullName
            )
            SELECT
                 ListID = x.c.value('ListID[1]','VARCHAR(36)')
                ,TimeCreated = x.c.value('TimeCreated[1]','DATETIME')
                ,TimeModified = x.c.value('TimeModified[1]','DATETIME')
                ,EditSequence = x.c.value('EditSequence[1]','VARCHAR(16)')
                ,Initial = x.c.value('Initial[1]','VARCHAR(5)')
                ,IsActive = x.c.value('IsActive[1]','BIT')
                ,SalesRepEntityRef_ListID = x.c.value('SalesRepEntityRef[1]/ListID[1]','VARCHAR(36)')
                ,SalesRepEntityRef_FullName = x.c.value('SalesRepEntityRef[1]/FullName[1]','VARCHAR(41)')
            FROM
                @strXML.nodes('QBXML/QBXMLMsgsRs/SalesRepQueryRs/SalesRepRet') x(c)
            WHERE
                x.c.value('ListID[1]','VARCHAR(36)') NOT IN (SELECT ListID FROM dbo.qb_salesrep) 

COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RETURN
END CATCH

-因此,从quickbooks返回的响应不是格式良好的xml --它最终被切断了。我猜是因为xml中的数据太多了。因此,当它被传递到sql存储过程时--它锁定在insert/update上,因为它的xml格式不是很好。因此,我希望以某种方式验证xml,并能够检索小块。

我使用metaData在SalesRepQueryRq中获得了总记录计数。如果我在请求中将MaxReturned设置为50,那么一切都可以正常工作,不会有任何问题。

以下是来自web连接器的消息

描述: QBWC1042: ReceiveResponseXML失败错误消息:操作超时,请参阅QWCLog获得更多详细信息。记得打开日志。

我使用了QUICKBOOKS_LOG_DEVELOP,最后一行是receiveResponseXML()

代码语言:javascript
复制
Incoming XML response: <?xml version="1.0" ?> <QBXML> <QBXMLMsgsRs> <SalesRepQueryRs requestID="6" statusCode="0" statusSeverity="Info" statusMessage="Status OK"> <SalesRepRet> <ListID>31A0000-1193779738</ListID> <SalesRepEntityRef> <ListID>60F0002-1193780133</ListID> <FullName>*BRANDT&apos;S</FullName> </SalesRepEntityRef> </SalesRepRet>
.....
.....
</Sales

xml就是这样结束的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-28 20:40:48

-因此,从quickbooks返回的响应不是格式良好的xml

不,事情不是这样的XML返回是完全可以的。

我猜是因为xml中的数据太多了。

你的问题与大量的数据有关.但它实际上与来自QuickBooks的无效XML无关。

因此,当它被传递到sql存储过程时--它锁定在insert/update上,因为它的xml格式不是很好。

不,这不是事情爆炸的原因。

因此,我希望以某种方式验证xml,并能够检索小块。

不需要验证XML。返回的XML QuickBooks是完全有效的。

然而,将结果分解成更小的块是个好主意。

如果我在请求中将MaxReturned设置为50,那么一切都可以正常工作,不会有任何问题。

这是个很大的暗示。它与无效的XML无关.您的问题与在XML中返回多少结果有关。

描述: QBWC1042: ReceiveResponseXML失败错误消息:操作超时,请参阅QWCLog获得更多详细信息。记得打开日志。

现在我们到了重要的一步!

这是关键:

  • 操作超时了

不幸的是,您没有发布Web连接器日志文件的其余部分,因此我们没有获得其他有用的信息。

网络连接器有一个硬编码,2分钟的超时.如果您已经发布了其余的日志,我想我们会看到Web日志中的时间戳显示出Web连接器开始发送数据的时间间隔为2分钟,而当连接关闭时,错误出现在日志中。

我敢打赌,如果您对代码进行了基准测试,您还会看到您的代码需要超过2分钟才能处理来自QuickBooks的响应。

我使用了QUICKBOOKS_LOG_DEVELOP,最后一行是receiveResponseXML()

我假设您是从quickbooks_log SQL表中提取的。我敢打赌,如果您检查了您的列类型,您会发现列上的最大长度只是切断了XML,因为它不能将所有数据都放进列中。

不确定迭代器中是否有?

此时,您可以查看文档:

并且很容易确定不是,迭代器不支持SalesRepQueryRq

但是,您可以通过查询数据块来伪造迭代器。例如,使用NameRangeFilter

代码语言:javascript
复制
<NameRangeFilter> <!-- optional -->
<FromName >STRTYPE</FromName> <!-- optional -->
<ToName >STRTYPE</ToName> <!-- optional -->
</NameRangeFilter>

检索从AaAz的所有内容。然后,对BaBz也做同样的操作。然后,对于CaCz等,您最终会得到所有的数据,但以较小的块。

TLDR:看看剩下的日志。下一次,从日志中发布整个相关部分。更有可能的是,您的代码花费的时间太长,并且超时2分钟。

票数 1
EN

Stack Overflow用户

发布于 2017-01-27 07:35:45

好的,这在SQL-Server中是有效的:

代码语言:javascript
复制
declare @xml xml=
   '<?xml version="1.0" encoding="utf-8"?>
    <?qbxml version="3"?>
    <QBXML>
        <QBXMLMsgsRq onError="stopOnError">
            <SalesRepQueryRq>
                <ActiveStatus>ActiveOnly</ActiveStatus>
                <FromModifiedDate>2017-01-27T08:30:15</FromModifiedDate>
                <IncludeRetElement>ListID</IncludeRetElement>
                <IncludeRetElement>SalesRepEntityRef</IncludeRetElement>
            </SalesRepQueryRq>
        </QBXMLMsgsRq>
    </QBXML>';
select @xml;

您是如何将其传递给的?下面是一个related answer,它解释了编码和参数类型可能出现问题的原因。

提示:让Server中的参数为NVARCHAR(MAX)类型。我将开始在没有<? ... ?>的情况下传递XML (处理指令)。切断第一行,让我们从<QBXML>开始。并确保您在. $ last .中输入的日期是ISO8601 (2017-01-27T08:30:15)。

在Server中,可以将传入的字符串分配给XML类型的变量。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41886223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档