2014-12-04 26 views
0

我有一個程序,它從文本文件中讀取有關3D網格的信息,將數據存儲爲網格,對網格執行一些後處理,然後收集體積等信息,質心等Poco 1.5.2 C++ ODBC在插入時拋出異常

該程序有兩個線程: 主線程啓動第二個線程,讀取文件,執行處理,然後等待第二個線程。作爲處理的一部分,它將有關網格的信息放入隊列中。 第二個線程使用Poco ODBC連接到SQL Server,將其讀取的文件的一些初始信息放入數據庫表中,然後從隊列中獲取信息並組裝可能冗長的插入命令。完成後,它會提交命令,執行有關所執行操作結果的最終更新命令,然後讓主線程知道它已完成,並終止第二個線程。

一切正常,直到它提交大插入命令爲止。它拋出一個異常,我無法弄清楚爲什麼。

這裏我將簡單介紹一下正在執行的代碼。假設變量存在並被初始化。 我運行POCO命令是:

using namespace Poco; 
using namespace Poco::Data::Keywords; 
using namespace Poco::Data; 
ODBC::Connector::registerConnector(); 
Session session(SessionFactory::instance().create("ODBC", "Driver={SQL Server};Server=<hostname>;Database=<DB name>;Uid=<username>;Pwd=<password>;")); 

session << "INSERT INTO TableName1 (SourceFileName,UserName) VALUES (?,?)",use(_filename),use(username),now; 
session << "SELECT SCOPE_IDENTITY()", into(runID),now; //This always runs and returns 0. 
string queryString = "Insert into TableName2 (Field1, field2, field3, field4, ...) "+ 
     "VALUES (val1, val2, val3, val4, ...)"+ 
     ",(valA, valB, valC, valD, ...),..." 

session << queryString,now; 
Statement update(session); 
update << "UPDATE TableName1 SET Field2 = ?, Field3 = ?, Field4 = ? WHERE Field1 = ?", use(data2), use(data3), use(data3), use(identity); 
update.execute(); 
ODBC::Connector::unregisterConnector(); 
<send signal to main thread indicating being done.> 

我試圖找出一些關鍵的東西。

  1. 如何判斷會話處於什麼狀態?
  2. 有沒有辦法問波科出了什麼問題,並讓它打印錯誤信息?
  3. 是否有任何特殊的事情需要設置,以便能夠像我一樣在文本中指定一個大的插入語句?我嘗試過使用它?佔位符或執行單個語句,但總是給我一個例外。
  4. 有沒有辦法讓語句在相同的連接下執行?通常我會做INSERT INTO TableName1(...)VALUES(...)SELECT SCOPE_IDENTITY()全部作爲單個操作。我已經在SQL Server Management Studio中嘗試了我的命令,並且它可以正常工作。現在,它總是返回0,即NULL,就像在不同連接中運行的語句一樣。

的更多信息:

String query = "INSERT INTO TableName1 (SourceFileName,UserName) VALUES ('"+ __file + "','" + __username + "')"; 
    Statement insertStmt = (session << query); 
    try{insertStmt.execute(true);} 
    catch(Poco::Exception exc) 
    { 
     cout << exc.displayText() << endl; 
    } 
    try{session << "SELECT SCOPE_IDENTITY() as SCOPE_IDENTITY", into(runID), now; 
    cout << "Run ID: " << runID << endl;} 
    catch(Poco::Exception exc) 
    { 
     cout << exc.displayText() << endl; 
    } 

我非常感謝你的幫助或者我如何能改善這個問題的任何建議。

回答

1

: 有在會話類各種查詢的成員 - isConnected(),canTransact(),isTransaction()...(如果這是你在找什麼;如果沒有,請參見下答案)


1和2: 包裝你的語句轉換成try/catch塊:

#include "Poco/Data/ODBC/ODBCException.h" 
//... 
try 
{ 
session << "INSERT INTO TableName1 (SourceFileName, UserName) VALUES (?, ?) ",use(_filename),use(username),now; 
} 
catch(Poco::Data::ODBC::ConnectionException& ce){ std::cout << ce.toString() << std::endl; } 
catch(Poco::Data::ODBC::StatementException& se){ std::cout << se.toString() << std::endl; } 

3.: 我不認爲問題太大聲明。有一個可配置的內部設置,將字符串大小限制爲1K,但這適用於值字符串,而不是整個SQL語句。 如果你仍然認爲這是問題,你可以增加最大字段大小,如:

std::size_t fieldSize = 4096; //4K 
session.impl()->setProperty("maxFieldSize", Poco::Any(fieldSize)); 

4.: 波科::數據:: ODBC不分析或分析任何的SQL語句辦法;所以從這個角度來看,無論你的ODBC驅動程序如何工作都可以。

+0

謝謝,我能夠找出原來的異常是由於嘗試插入提供的值的數量與所列列數相比。我正在編輯原文,以反映我的下一個問題。 – 2014-12-05 21:15:02

+0

對問題4添加了答案。 – Alex 2014-12-05 21:52:45

+0

那麼,當我使用sql控制檯連接到odbc數據源時,我可以按順序運行命令,並獲得正確的響應。當我在Poco中運行它們時,SCOPE_IDENTITY()只返回0,當您從新連接調用SELECT SCOPE_IDENTITY()而不插入任何內容時會發生這種情況。 – 2014-12-05 22:02:41