//全局数据库连接
CDataSource m_glDataSource;CComBSTR str( "Provider=SQLOLEDB.1;Password=123;Persist Security Info=True;User ID=sa;Initial Catalog=testManage;Data Source=BP" );HRESULT hr=m_glDataSource.OpenFromInitializationString( str );//正确连接
//想用DBPROP_AUTH_INTEGRATED参数
//hr=m_glDataSource.Open(CLSID_SQLOLEDB,"testManage","sa","123",DBPROP_AUTH_INTEGRATED);
//提示不认识CLSID_SQLOLEDB if (!SUCCEEDED(hr))
AfxMessageBox("连接数据库失败!");//数据访问,插入,删除等:
//a.h
CSession m_Session;
//CCommand<CAccessor<CConChangeData> > m_Recordset;
CTable<CAccessor<CConChangeData> > m_Recordset;
//a.cpp
//打开会话
HRESULT hr=m_Session.Open( m_glDataSource );
if (!SUCCEEDED(hr))
{
AfxMessageBox("打开数据库会话失败!"); 
return FALSE;
}
CString strCon="select * from T_Mytable " ;
LPCTSTR SQL = (LPCTSTR)strCon; //-------------支持更新
CDBPropSet ps(DBPROPSET_ROWSET);
ps.AddProperty(DBPROP_IRowsetChange, true);
ps.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE);
//------------------
//m_Recordset.Open(m_Session,SQL);//如果用这个,CDBPropSet怎么设置支持更新??
m_Recordset.Open(m_Session, "T_ContractChange", &ps, 1);
//读取数据
while (m_Recordset.MoveNext() == S_OK)
{
//date
str_ChangeOrderDate = COleDateTime(m_Recordset.m_ChangeOrderDate.date).Format("%Y-%m-%d");
...........
}
//使用纪录集添加纪录
_tcscpy( m_Recordset.m_ProjectNo, _T( "aaaa" ) );
_tcscpy( m_Recordset.m_ProjectName, _T( "bbbb" ) ); HRESULT hr=m_Recordset.Insert(0,false);
//hr返回E_NOINTERFACE
//即CDataSource::open时没成功使用 DBPROP_AUTH_INTEGRATED 参数吗??
有什么办法??

解决方案 »

  1.   

    //msdn提供发出参数化查询例子如下:#include <atldbcli.h>CDataSource connection;
    CSession session;
    CCommand<CAccessor<CArtists> > artists;// Open the connection, session, and table, specifying authentication 
    // using Windows NT integrated security. Hard-coding a password is a major 
    // security weakness.
    connection.Open(CLSID_MSDASQL, "NWind", NULL, NULL, 
    DBPROP_AUTH_INTEGRATED);
    session.Open(connection);// Set the parameter for the query
    artists.m_nAge = 30;
    artists.Open(session, "select * from artists where age > ?");// Get data from the rowset
    while (artists.MoveNext() == S_OK)
    {
       cout << artists.m_szFirstName;
       cout << artists.m_szLastName;
    }
    用户记录 CArtists 类似于:class CArtists
    {
    public:
    // Data Elements
       CHAR m_szFirstName[20];
       CHAR m_szLastName[30];
       short m_nAge;
     
    // Column binding map
    BEGIN_COLUMN_MAP(CArtists)
       COLUMN_ENTRY(1, m_szFirstName)
       COLUMN_ENTRY(2, m_szLastName)
       COLUMN_ENTRY(3, m_nAge)
    END_COLUMN_MAP()
     
    // Parameter binding map
    BEGIN_PARAM_MAP(CArtists)
       SET_PARAM_TYPE(DBPARAMIO_INPUT)
       COLUMN_ENTRY(1, m_nAge)
    END_PARAM_MAP()
    };//msdn提供发出更新行集合例子如下:
    支持更新操作
    当用“ATL OLE DB 使用者向导”创建使用者时,可以通过选择三个复选框 Change、Insert 和 Delete 中的一个或多个来支持更新操作。选择这些复选框后,向导将适当地修改代码以支持所选的更改类型。但如果不使用向导,则需要将以下行集合属性设置为 VARIANT_TRUE 来支持更新: DBPROPVAL_UP_CHANGE 使您可以在某一行中更改数据值。 
    DBPROPVAL_UP_INSERT 使您可以插入一行。 
    DBPROPVAL_UP_DELETE 使您可以删除一行。 
    按如下所示设置这些属性:CDBPropSet ps(DBPROPSET_ROWSET);
    ps.AddProperty(DBPROP_IRowsetChange, true)
    ps.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE)
    如果一个或多个列是不可写的,则更改、插入或删除操作可能会失败。修改游标映射以更正此问题。
    更新行集合请参见
    使用 OLE DB 使用者模板 | CRowset | IRowsetChange 
    一个非常基本的数据库操作就是更新(或将数据写入)数据存储区。OLE DB 中的更新机制非常简单:使用者应用程序设置绑定的数据成员的值,并将这些值写入行集合;然后使用者请求提供程序更新数据存储区。使用者可以对行集合数据执行以下几种更新操作:在行内设置列值、插入行和删除行。为执行这些操作,OLE DB 模板类 CRowset 实现了 IRowsetChange 接口,并重写下列接口方法: SetData 在行集合的某一行中更改列值;它等效于 SQL UPDATE 命令。 
    Insert 向行集合中插入一行;它等效于 SQL INSERT 命令。 
    Delete 从行集合中删除行;它等效于 SQL DELETE 命令。 
    支持更新操作
    当用“ATL OLE DB 使用者向导”创建使用者时,可以通过选择三个复选框 Change、Insert 和 Delete 中的一个或多个来支持更新操作。选择这些复选框后,向导将适当地修改代码以支持所选的更改类型。但如果不使用向导,则需要将以下行集合属性设置为 VARIANT_TRUE 来支持更新: DBPROPVAL_UP_CHANGE 使您可以在某一行中更改数据值。 
    DBPROPVAL_UP_INSERT 使您可以插入一行。 
    DBPROPVAL_UP_DELETE 使您可以删除一行。 
    按如下所示设置这些属性:CDBPropSet ps(DBPROPSET_ROWSET);
    ps.AddProperty(DBPROP_IRowsetChange, true)
    ps.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE)
    如果一个或多个列是不可写的,则更改、插入或删除操作可能会失败。修改游标映射以更正此问题。在行中设置数据
    CRowset::SetData 在当前行的一个或多个列中设置数据值。以下代码设置绑定到 Products 表的“Name”和“Units in Stock”列的数据成员的值,然后调用 SetData 将这些值写入行集合的第 100 行:// Instantiate a rowset based on the user record class
    CTable<CAccessor<CProductAccessor> > product;
    CSession session;// Open the rowset and move to the 100th row
    product.Open(session, "Product", &ps, 1);  // ps is the property set
    product.MoveToBook(&book, 0);      // Assume that book is set to 100th row// Change the values of columns "Name" and "Units in Stock" in the current row of the Product table
    _tcscpy( product.m_ProductName, _T( "Candle" ) );
    product.m_UnitsInStock = 10000;// Set the data
    HRESULT hr = product.SetData( );
    向行集合中插入行
    CRowset::Insert 使用访问器中的数据创建并初始化新行。Insert 在当前行的后面创建一个全新的行;需要指定是将当前行递增到下一行还是保持当前行不变。可以通过设置 bGetRow 参数完成此操作:HRESULT Insert(int nAccessor = 0, bool bGetRow = false)
    false(默认值)指定当前行递增到下一行(在这种情况下它将指向被插入的行)。 
    true 指定当前行保持原来位置。 
    以下代码设置绑定到 Products 表的列的数据成员的值,然后调用 Insert 将一个具有这些值的新行插入到该行集合的第 100 行后面。建议设置所有列值以避免在新行中出现未定义的数据:// Instantiate a rowset based on the user record class
    CTable<CAccessor<CProductAccessor> > product;
    CSession session;// Open the rowset and move to the 100th row
    product.Open(session, "Product", &ps, 1);  // ps is the property set
    product.MoveToBook(&book, 0);      // Assume that book is set to 100th row// Set the column values for a row of the Product table, then insert the row
    product.m_ProductID = 101;
    _tcscpy( product.m_ProductName, _T( "Candle" ) );
    product.m_SupplierID = 27857;
    product.m_CategoryID = 372;
    _tcscpy( product.m_QuantityPerUnit, _T( "Pack of 10" ) );
    product.m_UnitPrice = 20;
    product.m_UnitsInStock = 10000;
    product.m_UnitsOnOrder = 5201;
    product.m_ReorderLevel = 5000;
    product.m_Discontinued = false;// You must also initialize the status and length fields before setting/inserting data
    // Set the column status values
    m_dwProductIDStatus = DBSTATUS_S_ISNULL;
    m_dwProductNameStatus = DBSTATUS_S_ISNULL;
    m_dwSupplierIDStatus = DBSTATUS_S_ISNULL;
    m_dwCategoryIDStatus = DBSTATUS_S_ISNULL;
    m_dwQuantityPerUnitStatus = DBSTATUS_S_ISNULL;
    m_dwUnitPriceStatus = DBSTATUS_S_ISNULL;
    m_dwUnitsInStockStatus = DBSTATUS_S_ISNULL;
    m_dwUnitsOnOrderStatus = DBSTATUS_S_ISNULL;
    m_dwReorderLevelStatus = DBSTATUS_S_ISNULL;
    m_dwDiscontinuedStatus = DBSTATUS_S_ISNULL;// Set the column length value for column data members that are not fixed-length types.
    // The value should be the length of the string that you are setting.
    m_dwProductNameLength = 6;             // "Candle" has 6 characters
    m_dwQuantityPerUnitLength = 10;        // "Pack of 10" has 10 characters// Insert the data
    HRESULT hr = product.Insert( );
      

  2.   

    问题解决了,是因为我不小心把m_Recordset.Close()了,但是同样想问m_Recordset.Open(m_Session,SQL);//如果用这个,CDBPropSet怎么设置支持更新??
      

  3.   

    //全局连接数据库代码
    //第一种连接方式
    //CComBSTR str( "Provider=SQLOLEDB.1;Password=123;Persist Security Info=True;User ID=sa;Initial Catalog=ContractManage;Data Source=BP" );
    //HRESULT hr=m_glDataSource.OpenFromInitializationString( str );
    //第二种连接方式
    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO,false);
    dbinit.AddProperty(DBPROP_AUTH_USERID,"sa");
    dbinit.AddProperty(DBPROP_AUTH_PASSWORD,"kunrui");
    dbinit.AddProperty(DBPROP_INIT_CATALOG,"ContractManage");
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE,"(local)");
    dbinit.AddProperty(DBPROP_INIT_LCID,(long)1033);
    dbinit.AddProperty(DBPROP_INIT_PROMPT,(short)4);
    HRESULT hr=m_glDataSource.OpenWithServiceComponents("SQLOLEDB.1",&dbinit); if (!SUCCEEDED(hr))
    AfxMessageBox("连接数据库失败!");
    //打开会话和纪录集CSession m_Session;
    CCommand<CAccessor<CConChangeData> > m_Recordset;
    //CTable<CAccessor<CConChangeData> > m_Recordset;void GetRowsetProperties(CDBPropSet* pPropSet)
       {
          pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
          pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_IRowsetScroll,true);
          //pPropSet->AddProperty(DBPROP_IRowsetChange, true);//-----
      pPropSet->AddProperty(DBPROP_CANHOLDROWS, true);
      //pPropSet->AddProperty(DBPROP_IRowsetUpdate,true);//--------
      pPropSet->AddProperty(DBPROP_BOOKMARKS, true);
      //支持更新
      pPropSet->AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE);
       }
    HRESULT hr=m_Session.Open( m_glDataSource);
    if (!SUCCEEDED(hr))
    {
    AfxMessageBox("打开数据库会话失败!"); 
    return FALSE;
    } CString strCon="select * from T_ContractChange " ;//where ProjectNo='sdkjfowei' order by ProjectNo";
    LPCTSTR SQL = (LPCTSTR)strCon;
    //-------------支持更新
    CDBPropSet ps(DBPROPSET_ROWSET);
    m_Recordset.GetRowsetProperties(&ps);
    //------------------
    hr=m_Recordset.Open(m_Session,SQL,&ps);
    //m_Recordset.Open(m_Session, "T_ContractChange", &ps, 1);
    if (!SUCCEEDED(hr))
    {
    AfxMessageBox("打开记录集失败!"); 
    return FALSE;
    }
    //添加新记录
    CBook<0>              book;
    m_Recordset.MoveToBook(book, 0);
    char buff[100];
    //char
    ZeroMemory(buff,100);
    GetDlgItemText(IDC_EDIT1,buff,100);
    _tcscpy( m_Recordset.m_ProjectNo, buff );
    ZeroMemory(buff,100);
    GetDlgItemText(IDC_EDIT2,buff,100);
    _tcscpy( m_Recordset.m_ProjectName, buff );
    ZeroMemory(buff,100);
    GetDlgItemText(IDC_EDIT3,buff,100);
    _tcscpy( m_Recordset.m_Measure, buff );
    .............
    HRESULT hr=m_Recordset.Insert();如果是//CTable<CAccessor<CConChangeData> > m_Recordset;则insert成功,如果是
    CCommand<CAccessor<CConChangeData> > m_Recordset;则insert 不成功,返回E_NOINTERFACE错误。why????????????????????????????????
      

  4.   

    你的这个Accessor不是动态的,CCommmand应该也能Insert的吧
    就网上看到的信息来判断,动态Accessor是无法使用Insert的,烦
    只能自己构造SQL来执行Insert
      

  5.   

    hr=m_Recordset.Open(m_Session,SQL,&ps,NULL,DBGUID_DEFAULT,true,1);
    就算把参数写完也不行的。
    CTable都可以插入,CCommand就不可以插入,奇怪了。
      

  6.   

    E_NOINTERFACE错误和COM_INTERFACE_ENTRY有关么?怎么解决
      

  7.   

    #pragma once#include <atldbcli.h>class CConChangeData
    {
    public:
    // Data Elements
    CHAR m_GuidNo[100];
    CHAR m_ProjectNo[50];
    CHAR m_ProjectName[100];
    double m_ChangeAmount;
    double m_ChangeMoney;
    CHAR m_ChangeOrder[50];
    int m_ChangeIssue;
    ............

    void GetRowsetProperties(CDBPropSet* pPropSet)
       {
          pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
          pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_IRowsetScroll,true);
          //pPropSet->AddProperty(DBPROP_IRowsetChange, true);//-----
      pPropSet->AddProperty(DBPROP_CANHOLDROWS, true);
      //pPropSet->AddProperty(DBPROP_IRowsetUpdate,true);//--------
      pPropSet->AddProperty(DBPROP_BOOKMARKS, true);
      //支持更新
      pPropSet->AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE);
       }
    // Column binding map
    BEGIN_COLUMN_MAP(CConChangeData)
    COLUMN_ENTRY(1, m_GuidNo)
    COLUMN_ENTRY(2, m_ProjectNo)
    COLUMN_ENTRY(3, m_ProjectName)
                      ....................
    END_COLUMN_MAP()
     
    // Parameter binding map
    /*BEGIN_PARAM_MAP(CContrctBill)
    SET_PARAM_TYPE(DBPARAMIO_INPUT)
    COLUMN_ENTRY(1, m_ProjectNo)
    END_PARAM_MAP()*/
    };