

Blob file
#1
Posted 22 December 2006 - 04:56:36 PM

#2
Posted 23 December 2006 - 08:11:00 AM
ง่า เนื่องจากกระทู้หายไปแว้ว จึงขอถามคุณ jacky เอาดื้อๆเยย ว่า ตอนนั้นคุณ jacky post เรื่อง blob file เอาไปทำประโยชน์อะไรได้นอกจากเกบไฟล์รูปนะครับ รบกวนตอบไว้หน่อย หรืออธิบายซ้ำเยยก็ยิ่งดี จ๊วบบบ

หุหุ คือที่จริงแล้ว BLOB Field นั้นเราสามารถเอาไว้เก็บอะไรก็ได้ครับ คือมันเก็บเป็น Binary เช่นเก็บไฟล์เอกสาร Word,Excel หรือรูปภาพ ซึ่งถ้าใครใช้เดลไฟและ FastReport ในการทำงานนั้นเราสามารถเก็บตัวรายงานของ FastReport ลงใน Database ได้เลย เพราะตัว FastReport เองมี Method ชื่อ "LoadFromStream" ซึ่งเราสามารถใช้ Method นี้ load เอาไฟล์รายงานที่เก็บไว้ใน Database ได้ในทันที ข้อดีของการทำแบบนี้คือทุกๆ client นั้นจะใช้รายงานตัวเดียวกันทั้งหมด ไม่มีรายงานของเครื่องใครเครื่องมัน คือคุณสามารถทำ Centralize Management ได้แบบว่าปรับปรุงที่เดียวที่เหลือเหมือนกันหมดครับ
แต่ที่ผมเอามาโพสในบอร์ดคือการเก็บพวก Setup Security ให้แต่ละ user ครับ แบบว่าพวกการ lock menu ต่างๆ ซึ่งที่ผมเคยใช้คือการ lock กี่เมนูก็สร้าง field เท่าจำนวนเมนูที่ต้องการ lock ซึ่งถ้าต่อไปมีการเพิ่ม menu ก็ต้องแก้ทั้ง database และแก้โปรแกรม แต่ถ็ใช้ BLOB นั้นเราสามารถสร้างเพียง Field เดียวเพื่อใช้เก็บได้ครับ
ส่วนตัวอย่างนั้นแบบว่าลืมไปบ้างแล้ว ขอเวลาไปเรียบเรียงให้ดีก่อนนะครับ เพราะรู้สึกว่าคราวที่แล้วอธิบายค่อนข้างรวบรัดไปนิดนึง แล้วจะเข้ามาโพสใหม่ครับ
#3
Posted 23 December 2006 - 11:30:13 AM
#4
Posted 23 December 2006 - 11:42:53 AM
มันคืออะไร อ่านแล้วมะเก็ตเลยงับท่าน -..-
คำว่า BLOB ของเดลไฟมันย่อมาจาก Binary Large Object ครับ เทียบกับ Field Type ใน SQL Server ก็เท่ากับพวกที่เป็น Image คือใช้เก็บพวกรูปภาพหรือไฟล์ที่เป็น Binary ครับ แล้วผมก็เลยเอามา Apply เก็บพวก Secure ต่างๆของโปรแกรมไว้ใน Field นี้ไงครับ เอาไว้มาอธิบายแบบละเอียดจะเห็นภาพชัดกว่า ขอไปเรียบเรียงก่อนนะครับ แล้วจะมาตอบใหม่
แล้วจะเอา code ของการเก็บรายงานไว้ใน Database มาให้ดูด้วย หุหุ VB ทำได้เป่า Crystal Report ทำได้มั้ย หุหุ เกลียดมัน แต่ก็ยังหากินกะมัน ทั้งๆที่เกลียด อะจึ๋ย เด็กมหาลัยทำไมชอบใช้กันจัง
#5
Posted 25 December 2006 - 05:13:41 PM
อย่างถ้าไปทำappขึ้นมาตัวนึง จะมีพวกเจ้ากี้เจ้าการมาแบ่ง security คนนั้นเข้าformนี้ไม่ได้ ปุ่มนี้กดได้ คนนั้นห้ามกดปุ่มนี้ ปุ่มนี้ disable ปุ่มนั้น enable ถ้าไปนั่งcodeก็จะรู้สึกว่าทำไมมันไม่เป็นระเบียบเลยว้า เพิ่มปุ่มขึ้นมาก็ต้องไปนั่งแก้อีก ประมาณนี้อ่ะครับ คุง jacky เค้าใช้ blob field มาทำหน้าที่จัดระเบียบให้
แล้วคุง Jacky แน่น C ด้วยไหมง้าบ จะได้มารบกวนอีก จ๊วบบบ ล่วงหน้า
#6
Posted 25 December 2006 - 08:34:08 PM
ปล.เปลี่ยนมาใช้ delphi ซะดีมั้ยนี่
#7
Posted 26 December 2006 - 08:02:31 AM
จ๊วบบบบบ ขอบคุณค้าบบ เผื่อไม่เห็นภาพ ----
อย่างถ้าไปทำappขึ้นมาตัวนึง จะมีพวกเจ้ากี้เจ้าการมาแบ่ง security คนนั้นเข้าformนี้ไม่ได้ ปุ่มนี้กดได้ คนนั้นห้ามกดปุ่มนี้ ปุ่มนี้ disable ปุ่มนั้น enable ถ้าไปนั่งcodeก็จะรู้สึกว่าทำไมมันไม่เป็นระเบียบเลยว้า เพิ่มปุ่มขึ้นมาก็ต้องไปนั่งแก้อีก ประมาณนี้อ่ะครับ คุง jacky เค้าใช้ blob field มาทำหน้าที่จัดระเบียบให้
แล้วคุง Jacky แน่น C ด้วยไหมง้าบ จะได้มารบกวนอีก จ๊วบบบ ล่วงหน้า
c++ ทิ้งมันไปตั้งแต่เรียนจบปี 1 แล้วล่ะครับ ยังไม่ได้จับเลย แล้วพอมาจับเดลไฟก็ โอ้แม่เจ้านี่ล่ะที่หามานาน เขียนง่ายสไตล์ VB แต่ performance สุดยอดระดับ c++
#8
Posted 26 December 2006 - 09:35:17 AM
1. เก็บรายงานของ FastReport ไว้ใน DB
ตัวอย่างนี้ใช้ฐานข้อมูลของ Access นะครับ ส่วนใครจะไปปรับปรุงกับฐานข้อมูลตัวอื่นก็ได้นะครับ
ผมสร้างฐานข้อมูลไว้ในตารางชื่อ Report นะครับ มีโครงสร้างดังนี้
ID AutoNumber
ReportDescription text(255)
ReportFile OLE Object
ผมใช้งาน Component ADO และ FastReport 2.53 นะครับ สำหรับผู้ที่ต้องการทดสอบคงต้องไปหา FastReport 2.53 มาใช้แล้วล่ะ เพราะ ADO มีติดมากะเดลไฟอยู่แล้ว
ขั้นตอนการทำก็คือ
1. แปะ component ADOConnection ลงมาบนฟอร์มหรือ DataModule ก็ได้แล้วแต่สะดวก หลังจากนั้นก็กำหนด ConnectionString ไปยัง Database
2. แปะ component ADODataSet หรือถ้าใครถนัดจะใช้ ADOTable หรีอ ADOQuery ก็ได้อันนี้แล้วแต่ แต่ อ.จิรายุบอกว่าใช้ ADODataset จะเร็วกว่า ส่วน ADOTable กะ ADOQuery มันทำมาสำหรับคนที่เคยใช้ BDE จะได้เคยชิน
3. ที่ ADODataset กำหนด property ดังนี้
CommandType = cmdText
CommandText = select * from Report
4. สมมติว่าเราตั้งชื่อ ADOdataset ว่า Report นะครับ หลังจากนั้นเราคลิกว่าที่ ADODataset แล้วเลือก Field Editor หลังจากนั้นก็คลิกขวา เลือก Add All Field
5. เดลไฟก็จะสร้าง Persistance Field ขึ้นมาให้ตามจำนวน Field ที่เรา Select มา โดยเอาชื่อ ADODataset + ชื่อ Field และกำหนดชนิดข้อมูลตามที่เราประกาศไว้ใน Db ให้อัตโนมัติ ซึงจากตัวอย่างจะได้ดังนี้
ReportReportDescription: TWideStringField;
ReportReportFile: TBlobField;
ซึ่งพระเอกของตัวอย่างนี้ก็คือ ReportReportFile ซึ่งเป็น TBlobField นั่นเองครับ ไว้ต่อกระทู้หน้านะครับ
#9
Posted 26 December 2006 - 10:10:00 AM
7. แปะ component frReport และ frDesigner ลงมา
อันนี้เป็น Object ทั้งหมดในฟอร์มนะครับ ดูพวก component ที่แปะทั้งหมด แล้วก็ค่า property ต่างๆตามนี้นะครับ
Left = 253
Top = 159
Width = 320
Height = 174
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object btnRun: TSpeedButton
Left = 286
Top = 121
Width = 25
Height = 25
Caption = 'R'
OnClick = btnRunClick
end
object btnDesign: TSpeedButton
Left = 260
Top = 121
Width = 25
Height = 25
Caption = 'D'
OnClick = btnDesignClick
end
object DBGrid1: TDBGrid
Left = 0
Top = 0
Width = 310
Height = 120
DataSource = dsReport
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
Columns = <
item
Expanded = False
FieldName = 'ID'
Title.Alignment = taCenter
Width = 50
Visible = True
end
item
Expanded = False
FieldName = 'ReportDescription'
Title.Alignment = taCenter
Width = 150
Visible = True
end>
end
object DBNavigator1: TDBNavigator
Left = 0
Top = 121
Width = 260
Height = 25
DataSource = dsReport
TabOrder = 1
end
object Con: TADOConnection
Connected = True
ConnectionString =
'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Documents and Se' +
'ttings\suphonchai\Desktop\à¡çºÃÒ§ҹäÇéã¹ DB - á¡éä¢ÍêÍ»à¨ç¤µÍ¹Ã' +
'ѹä·Áì\fr2\dbReport.mdb;Persist Security Info=False'
LoginPrompt = False
Mode = cmShareDenyNone
Provider = 'Microsoft.Jet.OLEDB.4.0'
Left = 24
Top = 8
end
object Report: TADODataSet
Connection = Con
BeforePost = ReportBeforePost
AfterPost = ReportAfterPost
OnNewRecord = ReportNewRecord
OnPostError = ReportPostError
CommandText = 'select * from Report'
Parameters = <>
Left = 24
Top = 56
object ReportID: TAutoIncField
FieldName = 'ID'
ReadOnly = True
end
object ReportReportDescription: TWideStringField
FieldName = 'ReportDescription'
Size = 255
end
object ReportReportFile: TBlobField
FieldName = 'ReportFile'
end
end
object dsReport: TDataSource
DataSet = Report
OnStateChange = dsReportStateChange
OnDataChange = dsReportDataChange
Left = 72
Top = 56
end
object frDesigner1: TfrDesigner
CloseQuery = False
Left = 256
Top = 72
end
object frReport1: TfrReport
InitialZoom = pzDefault
PreviewButtons = [pbZoom, pbLoad, pbSave, pbPrint, pbFind, pbHelp, pbExit]
StoreInDFM = True
RebuildPrinter = False
Left = 216
Top = 72
ReportForm = {
19000000A5000000190000000015004850204C617365724A6574203231303020
50434C3600FFFFFFFFFF010000006F080000EA0A000000000000000000000000
00000000000000FFFF00000000FFFF000000000000000000000000030400466F
726D000F0000FFDC000000780000007C0100002C01000004000000FEFEFF0000
00000000000000000000FC000000000000000000000000000000005800A559DA
06AD14E34090D90A60AD14E340}
end
object frOLEObject1: TfrOLEObject
Left = 104
Top = 16
end
object frCheckBoxObject1: TfrCheckBoxObject
Left = 176
Top = 16
end
object frRichObject1: TfrRichObject
Left = 144
Top = 16
end
object frShapeObject1: TfrShapeObject
Left = 232
Top = 16
end
object frBarCodeObject1: TfrBarCodeObject
Left = 208
Top = 16
end
object frChartObject1: TfrChartObject
Left = 152
Top = 32
end
object frRoundRectObject1: TfrRoundRectObject
Left = 104
Top = 16
end
object frCrossObject1: TfrCrossObject
Left = 192
Top = 32
end
end
ส่วนอันนี้เป็น sourcecode นะครับแปะไว้ก่อนเด๋วค่อยไปเจาะลึกในรายละเอียด
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, ExtCtrls, DBCtrls, Grids, DBGrids, Buttons, FR_Class,
FR_Desgn, FR_Cross, FR_RRect, FR_Chart, FR_BarC, FR_Shape, FR_Rich,
FR_ChBox, FR_OLE;
type
TForm1 = class(TForm)
Con: TADOConnection;
Report: TADODataSet;
ReportID: TAutoIncField;
ReportReportDescription: TWideStringField;
ReportReportFile: TBlobField;
DBGrid1: TDBGrid;
dsReport: TDataSource;
DBNavigator1: TDBNavigator;
btnRun: TSpeedButton;
btnDesign: TSpeedButton;
frDesigner1: TfrDesigner;
frReport1: TfrReport;
frOLEObject1: TfrOLEObject;
frCheckBoxObject1: TfrCheckBoxObject;
frRichObject1: TfrRichObject;
frShapeObject1: TfrShapeObject;
frBarCodeObject1: TfrBarCodeObject;
frChartObject1: TfrChartObject;
frRoundRectObject1: TfrRoundRectObject;
frCrossObject1: TfrCrossObject;
procedure btnRunClick(Sender: TObject);
procedure btnDesignClick(Sender: TObject);
procedure dsReportStateChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ReportNewRecord(DataSet: TDataSet);
procedure ReportAfterPost(DataSet: TDataSet);
procedure ReportPostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
procedure dsReportDataChange(Sender: TObject; Field: TField);
procedure ReportBeforePost(DataSet: TDataSet);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnRunClick(Sender: TObject);
begin
frReport1.ShowReport;
end;
procedure TForm1.btnDesignClick(Sender: TObject);
begin
frReport1.DesignReport;
end;
procedure TForm1.dsReportStateChange(Sender: TObject);
begin
btnDesign.Enabled := dsReport.DataSet.State in [dsInsert,dsEdit];
btnRun.Enabled := dsReport.DataSet.State in [dsBrowse];
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Report.Open;
end;
procedure TForm1.ReportNewRecord(DataSet: TDataSet);
begin
frReport1.Clear;
end;
procedure TForm1.ReportAfterPost(DataSet: TDataSet);
begin
MessageDlg('ºÑ¹·Ö¡ÃÒ§ҹàÃÕºÃéÍÂáÅéÇ',mtInformation,[mbOk],0);
end;
procedure TForm1.ReportPostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
begin
raise Exception.Create(E.Message);
end;
procedure TForm1.dsReportDataChange(Sender: TObject; Field: TField);
begin
if not (Report.State in [dsInsert,dsEdit]) then
begin
frReport1.LoadFromBlobField(ReportReportFile);
end;
end;
procedure TForm1.ReportBeforePost(DataSet: TDataSet);
begin
frReport1.SaveToBlobField(ReportReportFile);
end;
end.
#10
Posted 26 December 2006 - 10:53:53 AM
procedure btnRunClick(Sender: TObject); <--------- ใช้ตอนแสดงรายงาน
procedure btnDesignClick(Sender: TObject); <--------- กดเพื่ออกแบบรายงาน
procedure dsReportStateChange(Sender: TObject); <---- เมื่อ Dataset ที่ link กับ dsReport มีการเปลี่ยนแปลง state จะทำอะไรบ้าง (ส่วนใหญ่จะใช้สำหรับความคุม enable,disable พวก control ต่างๆ)
procedure FormCreate(Sender: TObject); <---- ทำเมื่อฟอร์มนี้ถูกสร้างขึ้นมา
procedure ReportNewRecord(DataSet: TDataSet); <----- เกิด event นี่ต่อเมื่อเราเพิ่ม record ใหม่
procedure ReportAfterPost(DataSet: TDataSet); <--- Event จะเกิดขึ้นเมื่อหลังจากที่กดปุ่ม post
procedure ReportPostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction); <----- เมื่อ post ข้อมูลแล้วเกิดข้อผิดพลาด จะเกิด Event นี้
procedure dsReportDataChange(Sender: TObject; Field: TField); <---- เมื่อ Dataset มีการเปลี่ยนแปลงข้อมูล เราก็เช็คว่าถ้าไม่ใช้การ insert หรือ edit ก็ให้ load report มาเก็บเอาไว้ เพื่อรอให้ user กด view ดู
procedure ReportBeforePost(DataSet: TDataSet); <--- ก่อนที่จะบันทึกข้อมูลลง database จะทำอะไรบ้าง ในตัวอย่างนี้ก็จะเอา report ที่ทำการ design ไว้ล่าสุดเก็บลง TBlobField เพื่อที่จะบันทึกลงฐานข้อมูล
#11
Posted 26 December 2006 - 02:24:18 PM
OnStateChange = dsReportStateChange
OnDataChange = dsReportDataChange
end
object Report: TADODataSet
BeforePost = ReportBeforePost
AfterPost = ReportAfterPost
OnNewRecord = ReportNewRecord
OnPostError = ReportPostError
end
จะมีคนอ่านแล้วเข้าใจไหมหนอ

#12
Posted 05 January 2007 - 10:05:35 AM
อยากถาม concept 3tierหน่อยคับว่ามันเหมาะกับทุกcaseป่าว คือบางงานเป็นbatch ทำทีเปนแสนtransaction ต่อวัน มันเหมาะที่จะทำ 3tier ไหมหรือแค่ทำ script sql ยิงในoracleตรงๆจะดีกว่า แล้วยังงี้ 3tier มันจะเหมาะหรือไม่เหมาะกะbatch ขนาดใหย่ๆยังไง ให้ความรู้หน่อยค้าบ ><
#13
Posted 05 January 2007 - 10:23:07 AM
เข้าใจคับ ^^"
อยากถาม concept 3tierหน่อยคับว่ามันเหมาะกับทุกcaseป่าว คือบางงานเป็นbatch ทำทีเปนแสนtransaction ต่อวัน มันเหมาะที่จะทำ 3tier ไหมหรือแค่ทำ script sql ยิงในoracleตรงๆจะดีกว่า แล้วยังงี้ 3tier มันจะเหมาะหรือไม่เหมาะกะbatch ขนาดใหย่ๆยังไง ให้ความรู้หน่อยค้าบ ><
ผมก็ว่ามันก็น่าจะเหมาะนะครับ เพราะ concept 3-tier ของ delphi มันใช้งานร่วมกันกับ ClientDataSet ซึ่งทำงานบน memory ซึ่งเราสามารถทำงานกับ database แบบ connectionless ได้ นั่นหมายความว่าเราไม่ต้องทำการติดต่อ database ตลอดเวลาที่เราทำงานก็ได้ เพราะว่าเมื่อเรา retrive ข้อมูลมาแล้วเราสามารถตัด connection และยังทำงานต่อไปได้โดยที่ข้อมูลใน CDS(ClientDataSet) ไม่หายไปไหน แถมการทำงานแบบ 3-tier นั้นยังมีการ reconcile ข้อมูลที่ทำการแก้ไขใน record เดียวกันอีกด้วย
เช่น
ถ้าผมทำการแก้ไขใน Field Address แล้วทำการบันทึกลงไปก่อน ในขณะเดียวกันถ้าคุณ dokaponk แก้ไข Field Address เหมือนกันมันก็จะเกิด Event OnReconcileError ซึ่งเราสามารถกำหนดได้ว่าเราจะทำอย่างไรต่อไป เช่น Abort ไปเลย หรือกลับไปแก้ไขก่อน หรือ....ตามแต่ action ต่างๆที่เดลไฟมีครับ ซึ่งผมก็คิดว่า Feature 2 หลักๆนี้มันก็น่าจะดีกว่าการเขียนแบบ Client/Server แล้วนะครับ
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users