在DTL中,对数据进行插入和删除操作,目前发现有两种方法,一是用STL方法,一是用IndexDBView类操作;昨天就实验了这两种方法操作,DTL真不是一般的强大啊,可以像STL的操作,也可以直接执行SQL语句(ODBC封装貌似都可以吧),效率也还不错,当然,得选择合适的方法。(今天发现,对DTL操作,需要添加的库就是DTL和odbc2个即可,可以不添加odbcinst和stdc++库)
一、用index.htm自带的ReadData和WriteData进行操作,代码如下:
//将表内容存到vector
vector<Example> ReadData() {
vector<Example> results;
DBView<Example> view("example",Test());
DBView<Example>::select_iterator read_it = view.begin();
for ( ; read_it != view.end(); ++read_it)
{
results.push_back(*read_it);
}
return results;
}
//将vector到写到view
//用copy显然会重复;STL操作只能在末尾操作
void WriteData(const vector<Example> &examples)
{
DBView<Example> view("example",Test());
DBView<Example>::insert_iterator write_it = view ;
//此时view是在最后,怎么搞到begin位置呢?
copy(examples.begin(), examples.end(), write_it );
}
原带的read 和write方法,问题在于,写的时候,用的copy方法,而且不能将写的iterator调到开始对数据表进行重刷
vector<Example> results = ReadData();
DBView<Example> view("example",Test());
DBView<Example>::delete_iterator del_it = view ; //每次读出来先把表里面的内容删除
copy(results.begin(), results.end(), del_it );
Example E;
E.exampleInt=5;
E.exampleStr="insert5";
E.exampleDouble=6.4;
results.push_back(E);///
// 本方法的问题:WriteData中采用了copy方法切在末尾添加,表内容只增不减
WriteData(results);
其实这种方法与windows中ODBC封装的CRecordset感觉蛮像的,一次全部读到内存,映射,优点是操作方便,所有数据都读到了vector中;缺点是当数据表内容过大时耗时过多;
插入的另一种方式,是用variant_row,代码如下:
DynamicDBView<> view("example", "*");
DynamicDBView<>::insert_iterator write_it = view; //用insert_iterator插入
variant_row s(view.GetDataObj());
string str="insert";
s[0]= rand()%10;
s[1]=str; //直接赋值会得到错误
s[2]=3.3;
*write_it = s ;
write_it++;
STL方法操作db,方便,不过有2个局限性:a.如查找,需要手动的为每一个类写一个函数;b.STL只支持数据的单个index。STL操作,最大的问题在于,只能在数据表后面操作,不能调到view的前端进行操作。
二、IndexDBView类
IndexDBView的优点,如类介绍:Onemajor difference between the IndexedDBView container and a standard containeris that any changes made to the items in our container can be automaticallypropagated back to the database.任何改写会自动写到数据库(当然,得使用参数BOUND)
以删除代码为例,代码如下:(更多示范代码直接参考docs/IndexDBView.htm)
DBConnection::GetDefaultConnection().Connect("DSN=example;UID=sa;"
"PWD=123;server=127.0.0.1");
typedef DBView<Example, ParamObjExample> DBV;
DBV view("example", BCAExampleObj(),
"WHERE INT_VALUE BETWEEN (?) AND (?) OR "
"STRING_VALUE = (?) ORDER BY INT_VALUE",
BPAExampleObj());
IndexedDBView<DBV> indexed_view(
view,
"UNIQUE PrimaryIndex; STRING_VALUE; "
"AlternateIndex; INT_VALUE",
BOUND,
USE_ALL_FIELDS,
cb_ptr_fun(SetParamsExample));
IndexedDBView<DBV>::iterator idxview_it = indexed_view.begin();// .find(string("new"));
IndexedDBView<DBV>::iterator deleteMe = idxview_it; //都是删除相同的一大片啊
idxview_it++;
indexed_view.erase(deleteMe);
另外,删除数据后,可能有如下提示:
Exception type: DBException
Method: IndexedDBView::erase()
Error Message:Delete from DB failed! Record may have been changed by another user.
数据库显示正常,应该删除元素后迭代器失效,数据库中内容已经更新。
两种方法的耗时对比也很明显:
插入单条记录的时间测试效果如下:
| STL(s) | IndexDBView(us) |
10 | 0 | 0 |
100 | 0 | 0 |
1000 | 1.4 | 0 |
10000 | 2.5 | 0 |
删除单条记录耗时如下:
数量级 | 10 | 100 | 1000 | 5000 | 10000 |
用时(us) | 0 | 0 | 0 | 0 | 0 |
综和比较结果,可以认为:IndexDBView则结合了STL的便利性和SQL语句的效率吧
下面就是封装它的东东,提供接口给人使用了,刚搞定个连接和读取,sql_iterator什么的,居然有存储过程,想vc6的存储过程我也就写过一个,直接避过吧,先只是个简单的SQL语句算了。
说明下就是,记录情况为本人遇到,仅代表个人观点,如有问题,请留言。
菜鸟go go go ~~~