正好我最近做过这方面的内容,来谈一点体会。我的项目里,数据库使用的是Oracle,在表中对应prt文件的字段是BLOB类型,所以就直接使用了Oracle提供的OO4O,如果你使用的是其它数据库,请自行查阅相关资料。
以下是我的代码,首先是将prt文件保存入数据库
CString strPath,strSql,strFile;
OValue val;
tag_t Tag;
char* desc;
char path[256];
int closemode=0;
UF_PART_save();//保存当前正在编辑的文件
Tag=UF_PART_ask_display_part();//获得当前显示prt文件的tag
UF_PART_ask_description(Tag,[$desc)]
UF_PART_ask_part_name(Tag,path);//根据tag值获得当前文件的路径
UF_PART_close(Tag,1,closemode);//关闭当前文件
UF_UNDO_delete_all_marks();
strPath=(LPCSTR)(path);
if (strPath=="")
{
AfxMessageBox("当前没有被打开的文件,无法提交更新至数据库");
return;
}
//这种情况是在数据库中新建一条记录
//首先检查数据库中是否已经存在当前工序号所对应的记录,如果存在,就不进行新建操作
strSql="select sim_pic_name,sim_pic from propicinfo where op_id='" + cur + "' and sim_pic is not null";//cur是一个CString类型的变量,从外部传入,而sim_pic就是要保存的prt文件对应的BLOB字段
ds.Open(db,strSql);//db是一个Oracle的ODatabase,ds是一个Oracle的ODynaset,使用方法见OO4O文档
if (ds.GetRecordCount()!=0)
{
AfxMessageBox("当前工序的工序简图已经存在,无法新建!");
return;
}
//在新建工序图时,首先向数据库中插入包含当前工序号的一条记录
//同时把从prt文件完整路径中获得的文件名也赋给sim_pic_name字段
strSql="insert into propicinfo (op_id,sim_pic_name) values('" + cur + "','" + strFile + "')";
db.ExecuteSQL(strSql);
strSql="select sim_pic_name,sim_pic from propicinfo where op_id='" + cur + "' and sim_pic_name is not null";//再重新查询到刚才插入到数据库中的那条记录
ds.Open(db,strSql);
ds.StartEdit();
//由于此时sim_pic字段还没有被赋值,所以其值为NULL。根据OO4O的要求,先定义一个OValue
//然后将其值设为Emtpy(非NULL!),再将该Emtpy赋给sim_pic字段,对数据库提交更新。然后重新
//把sim_pic字段的值赋给lob,lob是一个OBlob类型的数据
val.SetEmpty();
ds.SetFieldValue((const char *)"sim_pic",val);
ds.Update();
ds.StartEdit();
ds.GetFieldValue("sim_pic",[$lob)]//把sim_pic字段与lob对象关联起来
StreamWrite(strPath);
//StreamWrite是一个几乎是从OO4O的例子中照搬过来的函数,它与UG没有任何的关系,它接受的唯一参数就是要提交到数据库中的文件的路径
StreamWrite(CString strPath)
{
oresult ores;
unsigned char *buffer = 0;
try
{
// calculate an optimum buffersize of approximately 32k bytes
unsigned long optchunk = lob.GetOptimumChunkSize();
unsigned int bufsize = ((int)(32768/optchunk)) *optchunk;
buffer = (unsigned char *)malloc(bufsize);
//open file and get file size
fstream fs;
fs.open(strPath, ios::in);
fs.setmode(filebuf::binary);
fs.seekg(0, ios::end);
unsigned long filesize = fs.tellg();
fs.seekg(0, ios::beg);
unsigned long totalwritten = 0;
unsigned long amtread = 0;
unsigned char piecetype = OLOB_FIRST_PIECE;
//By taking advantage of streaming we get the best performance
//and we don't need to allocate a huge buffer.
if (filesize <= bufsize)
piecetype = OLOB_ONE_PIECE;
else
lob.EnableStreaming(filesize);
while(totalwritten != filesize)
{
fs.read(buffer, bufsize);
amtread = fs.gcount();
lob.Write(buffer, amtread, piecetype);
totalwritten = totalwritten + amtread;
if ((filesize - totalwritten)<=bufsize)
piecetype = OLOB_LAST_PIECE;
else
piecetype = OLOB_NEXT_PIECE;
}
lob.DisableStreaming();
ores = ds.Update();
fs.close();
}
catch(OException E)
{
cout<<E.GetFailedMethodName()<< " Error: "<<E.GetErrorText()<<endl;
}
if (buffer)
free(buffer);
}
//这种情况是在编辑数据库中已经存在的一条记录中的那个BLOB字段
strSql="select sim_pic_name,sim_pic from propicinfo where op_id='" + cur + "' and sim_pic is not null";
ds.Open(db,strSql);
ds.StartEdit();
ds.GetFieldValue("sim_pic",[$lob)]
lob.Erase(lob.GetSize(),1);
StreamWrite(strPath);
我想从上面的代码里,你应该可以看得出来,真正与数据库相关联的就是StreamWrite函数,所以只要能够获得你要送入数据库的那个文件的路径就可以了。下一帖再说如何从数据库中读出,并在UG中显示出来。 |