关于在客户端利用TClientDataSet保存blob类型的字段问题

adventurezl 2003-04-03 05:45:13

创建一远程数据模块,添加组件并联接到一个数据库中,该数据库有一个大型二进制的字段(blob)FILE.客户端利用TClientDataSet进行更新,但是无法更新数据库,代码如下:
if (Edit2->Text.IsEmpty() )
return;
TMemoryStream *tmpStream = new TMemoryStream();
TBlobField *tmpField;
tmpStream->LoadFromFile(OpenDialog1->FileName);
client_DM->cdsFile_test->Close() ;
client_DM->cdsFile_test->Open() ;
client_DM->cdsFile_test->Edit();
client_DM->cdsFile_test->Append();
client_DM->cdsFile_test->Edit();
client_DM->cdsFile_test->FieldByName("ID")->AsString=Edit3->Text;
client_DM->cdsFile_test->FieldByName("NAME")->AsString=ExtractFileName(OpenDialog1->FileName);
tmpField = (TBlobField *)client_DM->cdsFile_test->FieldByName("FILE");
tmpField->LoadFromStream(tmpStream);
client_DM->cdsFile_test->Post() ;
client_DM->cdsFile_test->ApplyUpdates(-1);
tmpField = NULL;
delete tmpStream;

运行之后,只是在本地内存中修改,而无法保存到远程数据库中,请问原因何在?是不是ApplyUpdates函数不能保存blob类型的字段?
...全文
189 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
adventurezl 2003-04-11
  • 打赏
  • 举报
回复
问题终于解决了,多谢BCB(天下三分明月夜,二分无赖是扬州) ;马上结贴
BCB 2003-04-10
  • 打赏
  • 举报
回复
下面是我“人事档案”中的程序,我刚在三层DCOMConnection中试了完全成功!
.jpg或.bmp一律转换成.jpg存入字段,并能显示出!第二次打开,照片仍在!
再弄不明白就不应该了!

#include "jpeg.hpp"
void DispJpg() // 将字段中的.jpg图像--> Image1显示
{
TStream *bs=Form1->ClientDataSet1->CreateBlobStream(
Form1->ClientDataSet1->FieldByName("照片图像"),bmRead);
if(bs->Size>0)
{
TJPEGImage *j=new TJPEGImage;
bs->Position=0;
j->LoadFromStream(bs);
Form1->Image1->Picture->Bitmap->Assign(j);
delete j;
}
else
Form1->Image1->Picture=NULL;
delete bs;
}

void __fastcall TForm1::Button6Click(TObject *Sender)
{ // 将文件.bmp或.jpg以jpg 格式存入字段照片中
OpenDialog1->FileName="";
if (OpenDialog1->Execute())
{
String f=OpenDialog1->FileName;
if (FileExists(f))
{
String ext=ExtractFileExt(f).LowerCase();
if (ext==".bmp" || ext==".jpg"|| ext==".jpeg")
{
String jpg=ChangeFileExt(ExtractFileName(f),".jpg");
TJPEGImage *j=new TJPEGImage;
if (ext==".bmp")
{
Graphics::TBitmap *b=new Graphics::TBitmap;
b->LoadFromFile(f);
j->Assign(b);
j->CompressionQuality=90;
j->Compress();
delete b;
}
else
{
TFileStream *fs=new TFileStream(f,fmOpenRead);
j->LoadFromStream(fs);
delete fs;
}
ClientDataSet1->Edit();
TField *zd=ClientDataSet1->FieldByName("照片图像");
zd->Clear(); // 先清字段
TStream *bs=ClientDataSet1->CreateBlobStream(
zd,bmWrite);
bs->Position=0;
j->SaveToStream(bs);
delete j;
delete bs;
DispJpg();
}
}
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button7Click(TObject *Sender)
{
DispJpg();
}
void __fastcall TForm1::Button5Click(TObject *Sender)
{
if (ClientDataSet1->ChangeCount > 0)
ClientDataSet1->ApplyUpdates(-1); // 更新
ClientDataSet1->Close();

}
myy 2003-04-10
  • 打赏
  • 举报
回复
(回楼主短消息)

Sorry , 俺也不知道啊。。。
BCB 2003-04-10
  • 打赏
  • 举报
回复
Post()后再删,TBlobSream一定要用。
adventurezl 2003-04-10
  • 打赏
  • 举报
回复
楼上两位老大,还是不行啊!!to linlexing(拉拉叉) :你在post之前把ABlobStream 给delete了,那它被保存了么?我试了几次,程序在客户端是保存了,但是仍然没有提交到服务器端的数据库中。老大们,在想想办法。还有一个问题,就是保存时,为什么要用TBlobStream ?其它类型的Stream不行么?
BCB 2003-04-08
  • 打赏
  • 举报
回复
稍修改一下就成了
BCB 2003-04-08
  • 打赏
  • 举报
回复
你有两个错误:
1。没见你创建BlobStream;而只有TMemoryStream,
这是最大的错误!
TStream *tmpStream =DataSet1->CreateBlobStream(
zd,bmWrite);
2。流指针要重新回0;
tmpStream ->Position=0;
linlexing 2003-04-08
  • 打赏
  • 举报
回复
TBlobStream *ABlobStream = client_DM->CreateBlobStream(client_DM->cdsFile_test->FieldByName("FILE"),bmWrite) ;
ABlobStream->CopyFrom(tmpStream,0) ;
delete ABlobStream ; //一定要在Post之前删除
client_DM->cdsFile_test->Post() ;
client_DM->cdsFile_test->ApplyUpdates(-1);
tmpField = NULL;
delete tmpStream;
///以上的代码我用了N次了,包好
myy 2003-04-08
  • 打赏
  • 举报
回复
俺也不知道啊。。
adventurezl 2003-04-04
  • 打赏
  • 举报
回复
难道没人遇到过么?
winxp+delphi7+kbmmw4.0.3+unidac+mssql2000+dbgrideh 基本实现xalion中所说的功能并加上自己的一些编写经验 1、远程方法调用 2、取图像(流的使用) 3、查询数据 4、编辑数据:增、删、改(如果操作错误会进行相应的提示) 5、存储过程使用方法(存储过程参数自动创建) 6、动态创建数据集并执行Insert操作 7、命名查询(namedQuery) 8、事务操作(直接写SQL语句更新表的事务操作,有个重要的属性要设置,否则会更新不成功) 9、使用的数据库:sqlserver 2000,请到服务器的FDM单元把连接参数改下 10、数据库kbm_test结构参见:kbm_test.sql 11、安装kbmMw时请把配置文件 kbmMWConfig.inc中 {$DEFINE KBMMW_UNIDAC_SUPPORT} // UNIDAC support. 前面的//去掉 12、使用delphi7 2012年8月新增功能与说明 1、客户端断线重连:kbmMWTCPIPIndyClientTransport1.MaxRetries := 2;//重连一次 2、对象传输 3、JSON传输(利用kbmmw带的json库实现) 4、客户端断开代码: if FDM.kbmMWSimpleClient1.Transport.IsConnected then begin //memo1.Lines.Add('程序已有300秒没有进行操作,断开连接'); FDM.kbmMWSimpleClient1.Disconnect; end; 5、新增远程过程调用函数(直接SQL语句操作数据库): startTran:启动事务 commitTran:提交事务 rollbackTran:回滚事务 openSql:打开SQL语句 execSql:执行SQL语句 注openSql、execSql两个函数体代码使用对象连接池技术,无对象创建与释放,以提高系统效率, 具体能提高多少,未实测 6、增加HTTP协议例子(参考资料:kbmMW_and_AJAX.pdf),提供http-get的功能,http-post的功能可参照http-get方法实现 7、提供数据集转json与json转数据集 (CDSFromJSon(CDS:TClientDataSet;JsonStr:string):Boolean)单元:uDBJson.pas 参照代码可自行把json转kbmmwQuery kbmmw编译unidac方法: 修改单元kbmMWUNIDAC.pas,本人在数据库中很少用到blob字段,所以在代码里屏蔽掉blob字段的处理, 经测试数据库表字段类型为Text时,程序可以正常处理 报OLE DB error occured. CoInitialize has not been called (server)错误解决: unidac41src\Source\UniProviders\SQLServer\OLEDBAccessUni.pas constructor TOLEDBConnection.Create; begin inherited; CoInitialize(nil);//加此句 FCommand := nil; ... end; destructor TOLEDBConnection.Destroy; begin Disconnect; FCommand.Free; CoUninitialize;//加此句 inherited; end; 作者:chensm@vip.qq.com kbmmw开发交流群:209321818
很久没有发布东东了,今天看到盒子上有朋友发布了个三层的东东, 下来大概看了看,貌似使用起来不太方便,曾经用过ASTA和RmoObject,都不是那么让人满意,BUG多,并且庞大需要安装,使用十分不方便。 为了继续支持我喜欢的DELPHI和可爱的盒子, 特发布个自己写的远程数据库对象希望能给大家平常的工作带来便利和高效(偶自己和同事们都用了挺长时间,十分稳定易用)。 用DELPHI的朋友少不了要和数据库打交道,一般小程序都使用ACCESS或者SQLLITE做数据库感觉十分方便,不用装数据库服务端,客户端不用单独装驱动, 发布程序时直接目录一拷贝就完事,但缺点是不方便从其它计算机对它进行访问, 有了偶这个东东,就可以很方便容易的实现咯。 ps : 就是连接Oracle和mysql,也可以不用装驱动或少附带发布多余的DLL。 当前版本 mmzmagicrmo v1.8 更新历史 v1.0 单元实现 v1.1 解决不支持自增长字段问题 v1.2 解决id号必须是第1个字段问题 v1.3 为增加速度,做缓冲不用每次生成语句 ,改变自动更新时导致filter属性暂用的方式 v1.4 在sabason 兄的热心帮助下,解决了流试传输存在的问题,大大提高了传输效率 20100413 v1.5 全面修改为支持高效率的UniDAC数据库驱动套件 和ClientDataset (原来是ADO方式)支持所有主流数据库,大幅提高传输效率,且使用方法没有改变 v1.6 解决流传输存在的BUG ,修正最后一个字段blob字段导致语句生成错误的BUG v1.7 增加服务端sys.ini文件配置客户端登陆权限,增加批量执行SQL语句接口 v1.8 增加服务端提供自动升级功能,可以升级多个文件或者目录,可选择强制升级或者客户端可选升级 使用步骤 解压后找个地方存放 将GobUnit目录添加到delphi的搜索路径 将DXSockEnt30(我改过bug的版本)的3个子目录也添加到delphi的搜索路径 即可使用和编译所有偶提供的代码 FAQ: 这个东东都提供什么功能? 答:提供最简单方便高效的方式,通过CDS+UniDAC实现远程数据库 这个东东为什么不封装成控件? 答:本类以单元形式封装,只要加到搜索路径后直接引用即可,无需经过安装等麻烦的步骤。 这个东东适合应用在什么场合? 答:适合应用于小型分布式程序。 这个东东掌握起来有难度吗? 答:没有任何难度,就和你开发本地数据程序一样简单。 这个东东可以应用在我已有的程序里吗? 答:由于我使用的是TClientDataset作为数据集载体,所以无需更改为其他控件,现有的本地数据库程序也可以非常容易的改造为支持分布式数据库。 这个东东稳定吗? 答:经自己长期做小白鼠广泛的实际应用实践,发现方便,稳定。 服务端的端口号是多少? 答:服务端的端口号可以随意设置,只要不和其他程序冲突就可以,并且客户端连接服务端时必须端口一致. 如果服务端重启了客户端需要重启吗? 答:不用,客户端只要连接上服务端以后就有自动断线重连的功能。 我在使用时要注意什么? 答:如果你要用TClientDataset对象的Insert,Edit,Append,Post方法新增数据时,我会占用这个对象的BeforePost和BeforeDelete事件。 这个东东免费吗? 答:完全免费,并且开放所有源代码,你可以随意改进,传播它,当然如果更好用了,记得给我也发一份 :)(要保留偶的版权和注释信息哦) 这个东东使用到了那些控件? 答:第3方Dxsock,TClientDataset,UniDAC 同时发布的还有我自己积累的几个常用单元,有日志,调试,tcp的通用服务和客户端模块等,同样都是十分有用的东东。 这个东东有demo程序吗? 答:有最简单的示范程序,但时间关系只写了最简单的演示代码,还有很多值得你去挖掘的实用接口和单元。 我有了改进版本,怎么联系这个东东的作者? 答:QQ 22900104 ,Email 22900104@qq.com 马敏钊 发布这个东东的目的是什么? 答:好用的东东大家分享,共同学习,共同进步,希望大家都能发扬开源精神。 构架说明: 大概是这样的,偶有一个服务器对象,负责提供数据库服务,在需要提供数据服务的程序里创建它即可。 使用起来十分简单 首先引用服务端单元 uses UntRmodbSvr; //创建远程服务对象 (参数1 服务端口号 日志对象,如果不需要记录日志请填nil) Gob_RmoDBsvr := TRmodbSvr.Create(FSvrPort, nil); //连接数据库 可以是ADO支持的所有数据库 调用TDBMrg提供的获取各种数据库的链接字符串即可,这里连接Access数据库 Gob_RmoDBsvr.ConnToDb(TDBMrg.GetAccessConnStr('cfg.mdb')); 到此为止,2行代码使你的这个程序具有了将数据库发布出去的能力,其它机器的程序可以方便的通过它访问到数据库,像使用本地数据库一样。 客户端只需连接服务端即可,不管服务端是什么样的数据库,无需安装任何数据库驱动。 uses UntRemSql; //创建客户端对象 RmoClient := TRmoHelper.Create(); //连接服务端 填入服务端地址和端口(与服务端端口一致即可) Result := RmoClient.ReConnSvr(ISvrIP, Iport); 2行代码使你的客户端程序具有了方便的访问到远端的数据库,像使用本地数据库一样,并且你原有的单机数据库程序可以很方便改为远程数据库。 具体使用方法可以查看DEMO程序

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧