(billxu请进)求助:三层中保存blob数据的问题(Oracle8i)分数可再加 (100分)

  • 主题发起人 主题发起人 XiaoLiang
  • 开始时间 开始时间
X

XiaoLiang

Unregistered / Unconfirmed
GUEST, unregistred user!
Server 端放置 TDataBase,TQuery,TDataSetProvider
其中 TDataSetProvider 的 poAllowCommandText 为真
Client 端放置 SocketConnection,ClientDataSet1
其中 ClientDataSet1 的 FetchOnDemond = True,PacketRecord = -1
环境: Delphi 5+Servic Pack 1,Win 98 Oracle 8.1.6,bmp文件都很小 3K左右
程序如下:
存Bmp 文件
procedure Insert_Blob;
var
MyBlobStream :TMemoryStream;
begin
MyBlobStream := TMemoryStream.Create;
MyBlobStream.LoadFromFile('c:/aa.bmp');
MyBlobStream.Seek(0,soFrombegin
ning);
ClientDataSet1.Close;
ClientDataSet1.Params.Clear;
ClientDataSet1.CommandText := 'insert into my_bmp values(1,:bmp)';
ClientDataSet1.Params.CreateParam(ftBlob,'bmp',ptInput);
ClientDataSet1.Params.ParamByName('bmp').LoadFromStream(
MyBlobStream,ftBlob);
ClientDataSet1.Execute;
ClientDataSet1.CommandText := 'Commit';
ClientDataSet1.Params.Clear;
ClientDataSet1.Execute;
MyBlobStream.Free;
end;

取 bmp 数据 Image1 为 TImage
procedure Get_Blob;
var
aStream :TMemoryStream;
begin
aStream := TMemoryStream.Create;
ClientDataSet1.Close;
ClientDataSet1.CommandText := 'select id,bmp from sms_bmp where id=1';
ClienttDataSet1.Open;
ClientDataSet1.FetchBlobs;
TBlobField(ClientDataSet1.FieldByName('bmp')).SaveToStream(aStream);
aStream.SaveToFile('c:/bb.bmp');
aStream.Position := 0;
Image1.Picture.Bitmap.LoadFromStream(aStream);
aStream.Free;
end;

奇怪的问题:
在 Insert_Blob 中,我用 两层(TQuery 代替 TClientDataSet)能正确的存入数据,
用两层或三层的 Get_Blob 都能正确读出并显示。但我用 三层(即上面的语句)也能写入
数据库中,且读出时运行到 aStream.SAveToFile('c:/bb.bmp') 也能正确的写到
bb.bmp 中,用 画笔 能够打开并显示,但运行到 BitMap.LoadFromStream 时,
出 Stream Read Error .
比较 aa.bmp(源)与bb.bmp(从数据库中取出并存入),发现bb.bmp比aa.bmp
少了不少字节,且内容明显不同。
各位大侠能否帮我解释一下? (从画笔来看,aa.bmp 与 bb.bmp 简直一模一样).
另外还发现一个奇怪的事,那就是无论我把 DataSetProvider 的 poFetchBlobsOnDemand
如何设,ClientDataSet 的 FetchOnDemond,PacketRecord 如何设,且不用 FetchBlobs
我都能取到 blob 数据(好象跟书上讲得不太一样哟)。
在三层中到底该如何存取 blob 数据 ?
 
是呀,我也遇到了同样的问题。有那么一句:
Stream:=TBlobStream.Create(CDS_htmb.fieldbyname('mbnr') as TBlobfield,bmWrite);
在二层中好好的,在三层中就是过不了,好像报不能强制转换成二进制流。
 
你试一试用 TClientBlobStream, ClienttDataSet1的专用流
 
我今天用我的程序在 D6 试了一下,发现只能存 文本文件!!
到底在三层中如何增加一个 Blob 字段?
我用了 open;
edit;
insert;
tblobfield...loadFromFile;
post;
applyupdate(-1);
发现均不能存入 blob 数据? 恳请高手帮助解决!如觉分数不够可多加!
 
换个思路,不存 blob 数据,只存一个 blob 的地址(路径),这样就变成了STRING操作
 
我也遇到同样的问题,关注!
 
用这个,
procedure TForm1.SaveToClientBlob(ClientDataSet1:TClientDataSet;Blob:TField);
var
TargetField: TStream;
begin
TargetField := ClientDataSet1.CreateBlobStream(Blob, bmWrite);
TargetField.Position:=0;
try
Bitmap.SaveToStream(TargetField);
finally
TargetField.Free;
end;
end;
一点问题没有,我已经用过无数遍了。
 
to billxu:
我照您的意思写了如下程序,发现仍不能写入,请指教。
var
MyStream :TMemoryStream;
BStream :TStream;
begin
MyStream := TMemoryStream.Create;
MyStream.LoadFromFile('c:/aa.bmp');

MyStream.Postion := 0;
ClientDataSet1.Commandtext := 'select id,bmp from sms_bmp';
ClientDataSet1.open;
ClientDataSet1.Edit;
ClientDataSet1.Insert;
ClientDataSet1.FieldByName('id').Asinteger := 6;
BStream := ClientDataSet1.CreateBlobStream(ClientDataSet1.FieldByName('bmp'),
bmWrite);
BStream.Postion := 0;
MyStream.SaveToStream(BStream);
ClientDataSet1.Post;
ClientDataSet1.ApplyUpdates(-1);
.......
 
//save stream into dataset;
(ClientDataSet1.FieldByName('bmp') as tblobfield).loadfromstream(strm1);
//load stream from dataset;

(ClientDataSet1.FieldByName('bmp') as tblobfield).savetostream(strm1);
试试这个。
 
把MyStream改成
Bitmap1:TBitmap;
Bitmap1.SaveToStream(BStream);
再试试。
 
记得以前有人说过在oracle中,blob不能直接insert进去,需要先增加一个相应纪录
(次时blob字段为空),然后在update进去。你试试吧。
 
可能是读的问题,请试验如下程序:
procedure Get_Blob;
var
// aStream :TMemoryStream;
aStream :TClientBlobStream;
begin
// aStream := TMemoryStream.Create;
ClientDataSet1.Close;
ClientDataSet1.CommandText := 'select id,bmp from sms_bmp where id=1';
ClienttDataSet1.Open;
ClientDataSet1.FetchBlobs;
// TBlobField(ClientDataSet1.FieldByName('bmp')).SaveToStream(aStream);
aStream := ClientDataSet1.CreateBlobStream(ClientDataSet1.FieldByName('bmp'), bmRead);
// aStream.SaveToFile('c:/bb.bmp');
// aStream.Position := 0;
Image1.Picture.Bitmap.LoadFromStream(aStream);
aStream.Free;
end;
 
我一直都是这样做的:
TblobField(ClientDataSet1.FieldByName('bmp').asString).loadFromFile('c:/bb/bmp');
很好用
但是有一个问题,通过BDE连接ORCLE数据库(三层),不能INSERT,UPDATE, 请各位指教!
 
我也是这样用,没什么问题。
TBlobField(FieldByName('BlobFile')).SaveToFile
TBlobField(FieldByName('BlobFile')).LoadFromFile
我想和oracle什么关系吧。
poFetchBlobsOnDemand设为false是一定读不出的啊。
我都是用另一个sql语句去读写blob。大部份的操作不包含blob。
以前有过的问题是,当只有选出一个blob列时,不能插入,会出错。
 
我也碰过这样的问题。一般情况下是不能在clientdataset中使用commandtext的。
这跟oracle没有关系,MS SQL都是一样的。
函数GetBillHeadDetail是读取数据到本地,InWhereText是SQL语句,
其中BillHead_AQ:TAdoQuery;
BillHead_DSP:TDataSetProvider
函数SetBillHeadDetail是写入数据到服务器,InData是客户端TClientDataSet.Delta的
数据就是改动过的数据包
function TBillDo.GetBillHeadDetail(
const InWhereText: WideString): OleVariant;
begin

try
BillHead_AQ.Close;
BillHead_AQ.SQL.Add(InWhereText);
BillHead_AQ.Open;
Result := BillHead_DSP.Data;
SetComplete;
except
Setabort;
Raise;
end;

end;

function TBillDo.SetBillHeadDetail(InData: OleVariant;
out ErrorCount: Integer): OleVariant;
begin

try
Result := BillHead_DSP.ApplyUpdates(InData,0,ErrorCount);
SetComplete;
except
SetAbort;
Raise;
end;

end;

具体时,先送SQL语句“select * from TableName”记住就算你要新加也不要送
“insert into”等语句,用ClientDataSet.Data:=GetBillHeadDetail得到一空数据包,
再使用ClientDataSet.Append来新加,
这样你就可以用
TBlobField(FieldByName('BlobFile')).SaveToFile
TBlobField(FieldByName('BlobFile')).LoadFromFile
在处理。
处理完了就用SetBillHeadDetail(ClientDataSet.Delta,ErrCount)来更新
这里的参数ErrCount是没有什么用的是我要知道结果有多少个错误而已。
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部