Poco 1.5.2 C ++ ODBC在插入时抛出异常

时间:2014-12-04 21:00:13

标签: c++ sql-server-2008 odbc poco-libraries

我有一个程序,它从文本文件中读取有关3D网格的信息,将数据存储为网格,对网格执行一些后处理,然后收集体积,质心等信息。

该程序有两个主题:     主线程启动第二个线程,读取文件,进行处理,然后等待第二个线程。作为处理的一部分,它将有关刚刚读取的网格的信息放入队列中。     第二个线程使用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. 有没有办法问Poco出了什么问题,并打印出错误信息?
  3. 我需要设置一些特殊的东西才能像我一样在文本中一起指定一个大的插入语句吗?我试过用吗?占位符,或执行单个语句,但它总是在那个部分给我一个例外。
  4. 有没有办法让语句在同一个连接下执行?通常我会将INSERT INTO TableName1(...)VALUES(...)SELECT SCOPE_IDENTITY()全部作为单个操作。我在SQL Server Management Studio中尝试过我的命令,它运行正常。现在,它总是返回一个0 aka NULL,就像在单独的连接中运行的语句一样。
  5. 更多信息:

        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 个答案:

答案 0 :(得分:1)

<强> 1 即可。: Session类中有各种查询成员 - 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 即可。: Poco :: Data :: ODBC不以任何方式解析或分析SQL语句;所以从这个角度来看,无论使用哪种ODBC驱动程序都可以。