我正在使用Consoli字节提供的出色的Quickbooks,并将销售代表导入到数据库中。下面的代码是请求xml的代码。Quickbook文件有3000多个销售代表,响应xml无效。我知道我可以使用metaData获取计数,并使用MaxReturned获取有限的记录。不确定迭代器中是否有?
我将xml传递给mssql数据库并在那里解析它。问题是当xml无效时,它会导致sqlserver挂起,因为查询正在运行,所以在将xml传递给sql之前,我需要验证xml。
任何帮助都将不胜感激。
$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 --谢谢你花时间回复。下面是我对请求/响应功能的看法
//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的存储过程中的内容
@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()
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'S</FullName> </SalesRepEntityRef> </SalesRepRet>
.....
.....
</Salesxml就是这样结束的。
发布于 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:
<NameRangeFilter> <!-- optional -->
<FromName >STRTYPE</FromName> <!-- optional -->
<ToName >STRTYPE</ToName> <!-- optional -->
</NameRangeFilter>检索从Aa到Az的所有内容。然后,对Ba到Bz也做同样的操作。然后,对于Ca到Cz等,您最终会得到所有的数据,但以较小的块。
TLDR:看看剩下的日志。下一次,从日志中发布整个相关部分。更有可能的是,您的代码花费的时间太长,并且超时2分钟。
发布于 2017-01-27 07:35:45
好的,这在SQL-Server中是有效的:
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类型的变量。
https://stackoverflow.com/questions/41886223
复制相似问题