Technology for Business

Monday, April 15, 2013

Tản mạn tháng Tư

Chuyện Tấm Cám.
Ba đã được học: Rằng Tấm ở hiền gặp lành, rằng Cám xấu xa, độc ác, mẹ con nhà Cám bị quả báo, Cám bị muối xác cho mẹ Cám ăn…
Ba sẽ dạy lại con: không đâu con à, Tấm là người độc ác nhất trên thế gian này mà ba từng biết, mụ gì ghẻ là người đáng lên án, cón Cám thì vừa đáng trách lại vừa đáng thương.
Mẹ con nhà Cám vì mưu cầu hạnh phúc mà đã rắp tâm hãm hại người khác, năm Tấm bị hại chắc Cám cũng chưa đủ 18 tuổi, xét ra thì tội của Cám cũng chỉ là thấy người bị hại mà không cứu, thấy người khác làm điều ác mà không ngăn cản, lại đồng tình với mẹ để hại chị của mình.
Tấm bị hại cũng vì quá tin người, và cũng nên xét tới vấn đề là cây cau cao tới độ nào mà Tấm lại không thấy và phân biệt rõ được đâu hành động được cho là đuổi kiến của mụ gì ghẻ với đâu là hành động chặt cây. Nghỉ cũng lạ, một cô thôn nử đi mò cua bắt ốc hàng ngày ngoài sông lại té cây cau rồi chết đuối trong cái ao nhà! Một hoàng hậu được vua sủng ái lại không có lấy một bóng tùy tùng hộ giá.
Và trên đời này có ai nhẫn tâm như Tấm khi tưới nước sôi lên người đứa em ruột của mình cho tới chết, rồi đem xác muối thành mắm. Sự độc ác của Tấm lên đến tột cùng khi đem mắm của Cám cho người mẹ ruột của Cám ăn. Đến đoạn mẹ Cám nhìn thấy đầu con của mình trong hủ mắm mà lăn ra chết thì cho thấy thủ đoạn của Tấm được toan tính, được sắp đặt tỉ mỉ. Tấm đã bằng cách nào đó, cắt riêng đầu em mình ra và xử lý để không bị phân hủy trong hủ mắm, để còn nguyên hình nguyên dạng cho mẹ Cám nhìn ra con mình mà chết.
Độc ác và nhẫn tâm quá! Nếu cứ lấy oán báo oán thì thù hận cứ mãi không thôi.
Sống trên đời con phải luôn bao dung và sống lương thiện. Đừng vì mưu cầu hạnh phúc, vì lợi ích của bản thân mình mà làm hại người khác.
Chuyện Sơn Tinh – Thủy Tinh.
Ba đã được học: Thủy Tinh vì kém cỏi mà không lấy được vợ, hàng năm lại gây thiên tai lũ lụt để báo thù chàng Sơn Tinh.
Ba sẽ dạy lại con: Không đâu con à, chàng Thủy Tinh không kém cỏi mà là đề thi vốn dĩ không công bằng. Chàng Thủy Tinh vốn ở dưới biển sâu, làm sao có thể chuẩn bị cho kịp lể vật: “voi chín ngà, gà chín cựa, ngựa chín hồng mao” trong một sớm một chiều. Nếu lể vật là: “cua chín càng, cá chín mang, bào ngư chín mảng” thì mọi chuyện có lẻ đã khác.
Câu chuyện về cuộc chiến ngàn năm giữa Sơn Tinh và Thủy Tinh là một cách lý giải của dân gian về những đợt lũ lụt hàng năm. Nhưng thiên tai lũ lụt hàng năm đang xảy ra một phần lớn nguyên nhân là do con người: là sự phá hoại rừng đầu nguồn, khai thác tài nguyên vô tội vạ, là trái đất đang nóng lên và mực nước biển đang ngày một dâng cao.
Trong cuộc sống cần phải có sự đánh giá công bằng và trung thực. Và đừng vì là kẻ thua cuộc mà mang lòng thù hận, đừng vì một người đàn bà con gái mà hâm tâm tổn sức vào những chuyện không đáng.

15-April-2013

Thursday, March 03, 2011

Triển khai MVC 3 trên IIS 6.0 và Windows Server 2003


Cài đặt IIS, .Net Framework và MVC 3

Để triển khai một ứng dụng Web MVC 3 trên IIS 6.0 thì phải tiến hành cài đặt các ứng dụng như sau.

IIS 6.0

IIS 6.0 được tích hợp sẳn trên bộ cài Windows Server 2003 và chúng ta không thể cập nhật II 6.0 lên IIS 7.0 khi đang sử dụng hệ điều hành Windows Server 2003.

Để cài đặt IIS 6.0 thì vào Control Panel-> Add or Remove Programs, tiếp tục chọn Add/Remove Windows Components

Hình 1: chọn Application Server

Khi hộp thoại Windows Components Wizard hiện ra thì chọn Application Server và chọn Detais như hình 1.

Hình 2: chọn Internet Information Services (IIS)

Sau đó chọn Internet Information Services (IIS) và chọn OK.

Trong quá trình cài đặt thì yêu cầu bỏ đĩa cài Windows Server 2003 vào.

.Net Framework và MVC 3

Bước tiếp theo là tiếp tục cài đặt .Net Framework và MVC 3.

Sau khi cài đặt xong thì tiến hành đăng ký .Net Framework 4 với IIS 6.0 bằng cách thực thi aspnet_regiis.exe như hình 3.

Hình 3: đăng ký .Net Framework 4 với IIS 6.0

Cấu hình IIS 6.0 để thực thi ứng dụng web MVC 3

Thực hiện tùy chọn “Allow” cho ASP.NET v4 trong IIS.

Vào Administrative Tools -> Internet Information Services (IIS) Manager, sau đó chọn tiếp Web Service Extensions, thực hiện tùy chọn “Allow” theo hình 4.

Hình 4: Tùy chọn Allow cho ASP.NET v4

Cấu hình để IIS thực thi được kiểu URL mặc định của MVC 3

Thông thường sau khi tạo ứng dụng Web Site trên IIS cho MVC 3 và cho thực thi thì chúng ta sẽ gặp lỗi 404, là do IIS chưa được cấu hình định tuyến giữa các lớp M,V,C từ URL truyền vào, do đó IIS sẽ không thể tải lên được trang web mà chúng ta cần thực thi.

Chúng ta tiến hành bước cấu hình sau cho IIS.

Chọn Properties của ứng dụng Web trên IIS, sau khi hiện ra hộp thoại Properties thì chọn tiếp thẻ “Home Directory -> Configuration…” như hình 5.

Hình 5: chọn Configuration… cho mục web

Tiếp tục chọn thẻ Mappings, nếu tập tin aspnet_isapi.dll chưa được chọn thì chọn tiếp Insert… như hình 6.

Hình 6: Thêm vào file cấu hình mapping

Nhập đường dẫn tập tin aspnet_isapi.dll của phiên bản .Net Framework vào, trong ví dụ này sử dụng .Net Framwork 4.0.30319 trên Windows 64 bits thì đường dẫn là C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll. Nhớ không chọnVerify that file exists”, sau đó chọn OK như hình 7, và chọn OK như 8 để hoàn thành.

Hình 7: chọn tập tin aspnet_isapi.dll

Hình 8: hoàn thành việc thêm vào tập tin aspnet_isapi.dll

Việc cấu hình đã hoàn tất. Từ máy trạm bạn gõ vào địa chỉ của máy chủ vừa cấu hình để kiểm tra việc thực thi trang web MVC 3, kết quả sẽ như hình 9.


Hình 9: giao diện mặc định ban đầu của ứng dụng web MVC 3


TIPS: Khi triển khai trên windows 64 bits mà sử dụng ODP.NET, thì làm các bước sau:

  • Cài Oracle 11g Client, "software only"

  • Download ODAC XCopy, install odp.net4 và asp.net4, tạo thư mục odp.net và asp.net của OracleClient. Ví dụ: install.bat odp.net4 C:\OracleClient\odp.net OraClient11g_home1 false

Nếu sử dụng lưu cấu hình vào registry của hệ điều hành thì sử dụng aspnet_setreg.exe

  • aspnet_setreg.exe -k:SOFTWARE\MY_SECURE_APP\identity -u:"yourdomainname\username" -p:"password"
  • Gán quyền Read cho NETWORK_SERVICE ở Key HKLM\SOFTWARE\MY_SECURE_APP\identity\ASPNET_SETREG, lưu ý, đối với Windows 64 bits thì Key nằm ở HKLM\SOFTWARE\Wow6432Node\MY_SECURE_APP\identity\ASPNET_SETREG.

Thành phố Hồ Chí Minh, ngày 03/03/2011

Lê Đức Tâm - http://begin.vn

Tuesday, November 09, 2010

LẬP TRÌNH ORACLE VỚI ODP.NET [C#]

Bài viết dành cho các lập trình viên làm quen với việc lập trình cơ sở dữ liệu Oracle trên nền .NET.

“CHAT”

Sẽ có người hỏi sao lại lập trình Oracle với .NET nhỉ, thường thì nghe người ta nói với Oracle là phải Java, chẳng phải Oracle được phát triển bằng Java đó sao.

Bây giờ chúng ta coi như Oracle là quần jean, Java là áo bun (áo phong) còn .NET là áo sơ mi. Thường thì người ta mặc quần jean với áo bun, nhưng có một số trường hợp có thể mặc quần jean với áo sơ mi, đó có thể là:

Mặc quần jean với áo sơ mi mà nhìn vấn đẹp, có khi đẹp hơn ấy chứ.

Dạo này thấy người ta mặc quần jean với áo sơ mi nhiều nhỉ, phải theo thời trang chứ.

Và quan trọng là ở chỗ đó người ta chỉ cho phép mặc áo sơ mi!

Tốt nhất là không nên mất nhiều thời gian vào chuyện đó, cứ thấy phù hợp nhất đối với công việc của mình là được. Sau này có thời gian mình sẽ viết một bài về Web service + Java + Linux + Oracle, hoặc là những tips nhỏ sử dụng những đoạn chương trình Java ngay trong Oracle. Còn bây giờ nếu bạn quan tâm thì chúng ta bắt đầu. Mà để có thể bắt đầu được thì các bạn phải cài đặt Oracle Server, Oracle Client, .NET framework và viết thành công một chương trình nhỏ kết nối thành công tới Oracle. Về phần này mình không trình bày trong bài viết nên các bạn có thể tự tìm hiểu.

CÁC KIẾN THỨC CƠ BẢN

.NET

Đọc là “đốt nét”.

Hệ quản trị cơ sở dữ liệu Oracle

Điều cần nhắc tới ở đây đó là phiên bản đầu tiên của Oracle là Oracle 2. Điều này xem ra thật thú vị và đó cũng là một trong những kinh nghiệm hay về giới thiệu và quảng bá sản phẩm.

Cursor, Function, Procedure, Packet …

Là những khái niệm thường thấy trong bài viết này

Cursor: con trỏ, dùng lưu kết quả của câu lệnh select.

Ví dụ:

Cursor my_cursor is select * from ITS where 1 = 1;

Function: hàm, thực thi những tác vụ gì đó và trả về kết quả.

CREATE [OR REPLACE] FUNCTION [ (parameter [,parameter]) ]

RETURN
IS|AS

[declaration_section]
BEGIN

statements;

RETURN return_value;

[EXCEPTION

WHEN exception_name THEN

statements;]
END[function_name];

Ví dụ:

FUNCTION ITS_FUN (param1 IN VARCHAR2)

RETURN VARCHAR2

IS

BEGIN

RETURN param1;

END its_fun;

Procedure: gom các câu lệnh cần thực thi như select, update, insert, delete lại một chỗ và biên dịch một lần. Có tên gọi đầy đủ là store procedure hay còn thường được gọi là SP.

CREATE [OR REPLACE] PROCEDURE procedure_name

[ (parameter [,parameter]) ]

IS

[declaration_section]

BEGIN

executable_section

[EXCEPTION

exception_section]

END [procedure_name];

Ví dụ:

PROCEDURE its_proc (v_its_worktime IN NUMBER)

IS

BEGIN

UPDATE its

SET worktime = 0

WHERE worktime > v_its_worktime;

DELETE its

WHERE worktime > v_its_worktime;

END;

Package: gom các cursor,function, procedure … liên quan lại với nhau, đi kèm với package là package body – cài đặt chi tiết cho các SP và functions đã khai báo trong package.

Ví dụ: (Một package trong bài viết)

PACKAGE PAC_TABLE4

IS

-- Person Date Comments

-- ITS 08/10/2008

TYPE t_cursor IS REF CURSOR;

TYPE array_id IS TABLE OF NUMBER

INDEX BY PLS_INTEGER;

TYPE array_name IS TABLE OF VARCHAR (100)

INDEX BY PLS_INTEGER;

TYPE array_address IS TABLE OF VARCHAR (200)

INDEX BY PLS_INTEGER;

TYPE array_phone IS TABLE OF VARCHAR (25)

INDEX BY PLS_INTEGER;

PROCEDURE insert_data_asso (

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

);

PROCEDURE update_data_asso (

p_id IN array_id,

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

);

PROCEDURE delete_data_asso (p_id IN array_id);

PROCEDURE select_data (o_cursor OUT t_cursor);

END pac_table4;


ODP.NET

Tên tiếng anh

Một gói thư viện của Oracle dành cho lập trình Oracle với .NET, xem thêm tại link:

http://www.oracle.com/technetwork/topics/dotnet/whatsnew/index.html

Có một điểm lưu ý nhỏ là nếu như trong máy bạn đã cài đặt Oracle Client thì sau khi bạn cài đặt ODP.NET vào sau thì path sẽ ưu tiên thư mục bin của ODP.NET. Bạn vào start-run-cmd-path, sẽ thấy liệt kê path hiện thời của windows. Bạn có thể hiệu chỉnh thứ tự của path bằng cách vào My Computer-Properties-Advanced-Environment Variables – System variables – Path – Edit. Và nếu chọn path đầu tiên trỏ tới bin của Oracle Client hay bin của ODP.NET thì cũng phải tạo TNS tương ứng trong thu mục network-admin. Nếu không bạn sẽ gặp phải lỗi:

ORA-12154: TNS:could not resolve service name

TẠO MỘT PROJECT .NET

Bạn muốn dùng lại project có sẳn trong thư mục sourcecode đi kèm thì máy bạn phải cài đặt .NET framework 3.5 và dùng Visual Studio 2008.

Để sử dụng ODP.NET thì bạn phải Add Preference gói thư viện này vào. Như hình dưới đây thêm vào thư viện ODP.NET Oracle 9.2.


đây chỉ là một ứng dụng demo nên mình fix code luôn chuổi connectionString. Và TNS của mình là :

ITS_DB =

(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST = ITS)(PORT = 1521))

)

(CONNECT_DATA =

(SERVER = DEDICATED)

(SERVICE_NAME = ITS_DB)

)

)

và username và password login vào database của mình là:

Username: ITS, Password: its123456

Nên mình fix code:

private string connectionString = "Data Source=ITS_DB;User Id=ITS;Password=abc123456;";

(Chỉnh sửa tại file FormMain.cs line: 9, nhấn Ctrl+G và nhập số line để đến line cần tìm)

TRIỂN KHAI DATABASE

Bước 1: Tạo user để thử nghiệm chương trình. Ví dụ như mình tạo user: ITS, password: abc123456

Bước 2: Tạo table1, table1_seq

CREATE TABLE table1

(ID NUMBER(12,0),

NAME VARCHAR2(100),

address VARCHAR2(200),

phone VARCHAR2(25))

PCTFREE 10

INITRANS 1

MAXTRANS 255

TABLESPACE users

STORAGE (

INITIAL 65536

MINEXTENTS 1

MAXEXTENTS 2147483645

)

NOCACHE

NOMONITORING

CREATE SEQUENCE table1_seq

INCREMENT BY 1

START WITH 1

MINVALUE 1

MAXVALUE 999999999999999999999999999

NOCYCLE

NOORDER

CACHE 20

Bước 3: Tạo table2, table2_seq, pac_table2 (bao gồm body)

CREATE TABLE table2

(ID NUMBER(12,0),

NAME VARCHAR2(100),

address VARCHAR2(200),

phone VARCHAR2(25))

PCTFREE 10

INITRANS 1

MAXTRANS 255

TABLESPACE users

STORAGE (

INITIAL 65536

MINEXTENTS 1

MAXEXTENTS 2147483645

)

NOCACHE

NOMONITORING

CREATE SEQUENCE table2_seq

INCREMENT BY 1

START WITH 1

MINVALUE 1

MAXVALUE 999999999999999999999999999

NOCYCLE

NOORDER

CACHE 20

CREATE OR REPLACE

PACKAGE pac_table2

IS

-- Person Date Comments

-- ITS 08/10/2008

TYPE t_cursor IS REF CURSOR;

PROCEDURE insert_data (

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

);

PROCEDURE update_data (

p_id IN NUMBER,

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

);

PROCEDURE delete_data (p_id IN NUMBER);

PROCEDURE select_data (o_cursor OUT t_cursor);

END;

CREATE OR REPLACE

PACKAGE BODY pac_table2

IS

-- Person Date Comments

-- ITS 08/10/2008

PROCEDURE insert_data (

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

)

IS

BEGIN

INSERT INTO table2

(ID, NAME, address, phone

)

VALUES (table2_seq.NEXTVAL, p_name, p_address, p_phone

);

END;

PROCEDURE update_data (

p_id IN NUMBER,

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

)

IS

BEGIN

UPDATE table2

SET NAME = p_name,

address = p_address,

phone = p_phone

WHERE ID = p_id;

END;

PROCEDURE delete_data (p_id IN NUMBER)

IS

BEGIN

DELETE table2

WHERE ID = p_id;

END;

PROCEDURE select_data (o_cursor OUT t_cursor)

IS

BEGIN

OPEN o_cursor FOR

SELECT ID, NAME, address, phone

FROM table2;

END;

END;

Bước 4: Tạo table3, table3_seq, pac_table3 (bao gồm body)

CREATE TABLE table3

(ID NUMBER(12,0),

NAME VARCHAR2(100),

address VARCHAR2(200),

phone VARCHAR2(25))

PCTFREE 10

INITRANS 1

MAXTRANS 255

TABLESPACE users

STORAGE (

INITIAL 65536

MINEXTENTS 1

MAXEXTENTS 2147483645

)

NOCACHE

NOMONITORING

CREATE SEQUENCE table3_seq

INCREMENT BY 1

START WITH 1

MINVALUE 1

MAXVALUE 999999999999999999999999999

NOCYCLE

NOORDER

CACHE 20

CREATE OR REPLACE

PACKAGE pac_table3

IS

-- Person Date Comments

-- ITS 08/10/2008

TYPE t_cursor IS REF CURSOR;

PROCEDURE insert_data (

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

);

PROCEDURE update_data (

p_id IN NUMBER,

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

);

PROCEDURE delete_data (p_id IN NUMBER);

PROCEDURE select_data (o_cursor OUT t_cursor);

END;

CREATE OR REPLACE

PACKAGE BODY pac_table3

IS

-- Person Date Comments

-- ITS 08/10/2008

PROCEDURE insert_data (

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

)

IS

BEGIN

INSERT INTO table3

(ID, NAME, address, phone

)

VALUES (table3_seq.NEXTVAL, p_name, p_address, p_phone

);

commit;

END;

PROCEDURE update_data (

p_id IN NUMBER,

p_name IN VARCHAR2,

p_address IN VARCHAR2,

p_phone IN VARCHAR2

)

IS

BEGIN

UPDATE table3

SET NAME = p_name,

address = p_address,

phone = p_phone

WHERE ID = p_id;

END;

PROCEDURE delete_data (p_id IN NUMBER)

IS

BEGIN

DELETE table3

WHERE ID = p_id;

END;

PROCEDURE select_data (o_cursor OUT t_cursor)

IS

BEGIN

OPEN o_cursor FOR

SELECT ID, NAME, address, phone

FROM table3;

END;

END;

Bước 4: Tạo table4, table4_seq, pac_table4 (bao gồm body)

CREATE TABLE table4

(ID NUMBER(12,0),

NAME VARCHAR2(100),

address VARCHAR2(200),

phone VARCHAR2(25))

PCTFREE 10

INITRANS 1

MAXTRANS 255

TABLESPACE users

STORAGE (

INITIAL 65536

MINEXTENTS 1

MAXEXTENTS 2147483645

)

NOCACHE

NOMONITORING

CREATE SEQUENCE table4_seq

INCREMENT BY 1

START WITH 1

MINVALUE 1

MAXVALUE 999999999999999999999999999

NOCYCLE

NOORDER

CACHE 20

CREATE OR REPLACE

PACKAGE pac_table4

IS

-- Person Date Comments

-- ITS 08/10/2008

TYPE t_cursor IS REF CURSOR;

TYPE array_id IS TABLE OF NUMBER

INDEX BY PLS_INTEGER;

TYPE array_name IS TABLE OF VARCHAR (100)

INDEX BY PLS_INTEGER;

TYPE array_address IS TABLE OF VARCHAR (200)

INDEX BY PLS_INTEGER;

TYPE array_phone IS TABLE OF VARCHAR (25)

INDEX BY PLS_INTEGER;

PROCEDURE insert_data_asso (

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

);

PROCEDURE update_data_asso (

p_id IN array_id,

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

);

PROCEDURE delete_data_asso (p_id IN array_id);

PROCEDURE select_data (o_cursor OUT t_cursor);

END;

CREATE OR REPLACE

PACKAGE BODY pac_table4

IS

-- Person Date Comments

-- ITS 08/10/2008

PROCEDURE insert_data_asso (

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

)

IS

BEGIN

FORALL i IN p_name.FIRST .. p_name.LAST

INSERT INTO table4

(ID, NAME, address,

phone

)

VALUES (table4_seq.NEXTVAL, p_name (i), p_address (i),

p_phone (i)

);

END;

PROCEDURE update_data_asso (

p_id IN array_id,

p_name IN array_name,

p_address IN array_address,

p_phone IN array_phone

)

IS

BEGIN

FORALL i IN p_id.FIRST .. p_id.LAST

UPDATE table4

SET NAME = p_name (i),

address = p_address (i),

phone = p_phone (i)

WHERE ID = p_id (i);

END;

PROCEDURE delete_data_asso (p_id IN array_id)

IS

BEGIN

FORALL i IN p_id.FIRST .. p_id.LAST

DELETE table4

WHERE ID = p_id (i);

END;

PROCEDURE select_data (o_cursor OUT t_cursor)

IS

BEGIN

OPEN o_cursor FOR

SELECT ID, NAME, address, phone

FROM table4;

END;

END;

CHẠY CHƯƠNG TRÌNH

Bước 1:

Kiểm tra kết nối database.

Lớp thực thi việc kết nối và đóng kết nối, xem file ODPConnection.cs

using System;

using Oracle.DataAccess.Client;

namespace ODP_Demo

{

///

/// ODPConnection

///

/// ITS

/// 11/10/2008

public class ODPConnection : IDisposable

{

#region contruction

bool isDisposed = false;

private string connString = "";

private OracleConnection connection;

public ODPConnection(string pConnString)

{

this.connString = pConnString;

}

#endregion

#region Open and Close

///

/// Open Connection

///

/// OracleConnection

public OracleConnection Open()

{

try

{

connection = new OracleConnection(connString);

connection.Open();

}

catch

{

connection = null;

}

return connection;

}

///

/// Close Connection

///

public void Close()

{

try

{

if (this.connection != null && this.connection.State != System.Data.ConnectionState.Closed)

{

this.connection.Close();

connection.Dispose();

}

}

catch { }

}

#endregion

#region IDisposable

// Other managed resource this class uses.

private System.ComponentModel.Component component = new System.ComponentModel.Component();

~ODPConnection()

{

Dispose(false);

}

public void Dispose()

{

Dispose(true);

GC.SuppressFinalize(this);

}

protected virtual void Dispose(bool disposing)

{

if (!isDisposed)

{

if (disposing)

component.Dispose();

this.Close();

isDisposed = true;

}

}

#endregion

}

}

Bước 2: Tạo file dữ liệu để Insert vào database.

Xem chi tiết tại file iFunctions.cs

Phương thức tạo ngẫu nhiên một thông tin liên hệ, gồm tên, địa chỉ và số điện thoại.

private static string[] CreateContact(int i)

{

string[] item = new string[3];

Random random = new Random(i + new Random().Next(9999));

//Create Name

string[] firstName = new string[] { "Lê ", "Phạm ", "Nguyễn ", "Trần ", "Phan ", "Huỳnh ", "Hoàng ", "Võ ", "Đoàn " };

string[] middleName = new string[] { "Đức ", "Thúy ", "Minh ", "Phương ", "Quốc ", "Vĩnh ", "Ngọc ", "Quang ", "Hồng " };

string[] lastName = new string[] { "Tâm", "An", "Sơn", "Tuấn", "Trí", "Dũng", "Hương", "Trang", "Hằng" };

item[0] = firstName[random.Next(firstName.Length)] + middleName[random.Next(middleName.Length)] + lastName[random.Next(lastName.Length)];

//Create Address

string[] streets = new string[] { " Nguyễn Huệ, P.", " Lê Lợi, P.", " Hàm Nghi, P.", " Nam Kỳ Khởi Nghĩa, P.", " Võ Thị Sáu, P.", " Điện Biên Phủ, P.", " Trương Quyền, P.", " Phạm Ngọc Thạch, P." };

item[1] = random.Next(200).ToString() + streets[random.Next(streets.Length)] + random.Next(20).ToString() + ", Q." + random.Next(12).ToString() + ", TP.Hồ Chí Minh";

//Create Phone

string[] prefixNumber = new string[] { "090", "093", "0122", "091", "098", "095" };

item[2] = prefixNumber[random.Next(prefixNumber.Length)] + random.Next(9999999).ToString().PadRight(7,'0');

return item;

}

Phương thức lưu tập tin C:\\data_content.xm , chứa count số tài khoản cần tạo ngẫu nhiên.

public static bool WriteContacts(int count)

{

XmlTextWriter writer = null;

try

{

writer = new XmlTextWriter("C:\\data_content.xml", Encoding.UTF8);

writer.WriteStartDocument();

writer.WriteStartElement("contacts");

for (int i = 0; i <>

{

string[] item = CreateContact(i);

writer.WriteStartElement("name");

writer.WriteString(item[0]);

writer.WriteEndElement();

writer.WriteStartElement("address");

writer.WriteString(item[1]);

writer.WriteEndElement();

writer.WriteStartElement("phone");

writer.WriteString(item[2]);

writer.WriteEndElement();

}

writer.WriteEndDocument();

return true;

}

catch

{

return false;

}

finally

{

if(writer != null)

writer.Close();

}

}

Trong file FromMain.cs line 30, số tài khoản cần tạo đang mặc định là 10000. Lưu ý là bạn không nên tạo nhiều số tài khoản, vì khi bạn tiến hành bind dữ liệu lớn thì có thể gặp lỗi ví dụ như sau: ORA-01044: size 5700000 of buffer bound to variable exceeds maximum 4194304.

Việc kiểm tra buffer size, để tiến hành bind từng phần dữ liệu sẽ thảo luận sau.

Bước 3: Tiến hành Insert dữ liệu vào database. Xem chi tiết tại file ODPController.cs.

Trong chương trình này chúng ta sẽ kiểm tra thời gian insert dữ liệu vào database bằng 4 cách.

Cách 1 là dùng theo command text bình thường. Trong trường hợp này chúng ta gửi 10000 command đi đi về về yêu cầu insert về cho database server, và câu lệnh sẽ được biên dịch trước khi thực thi.

public static bool CTInsertData(OracleConnection pConnection, string[] pName, string[] pAddress, string[] pPhone)

{

OracleCommand command = new OracleCommand("INSERT INTO table1(ID, NAME, address, phone) VALUES(table1_seq.NEXTVAL, :p_name, :p_address, :p_phone)", pConnection);

command.CommandType = CommandType.Text;

try

{

for (int i = 0; i <>

{

//Bind Parameter

OracleParameter p_name = new OracleParameter("p_name", OracleDbType.Varchar2);

p_name.Direction = ParameterDirection.Input;

p_name.Value = pName[i];

command.Parameters.Add(p_name);

OracleParameter p_address = new OracleParameter("p_address", OracleDbType.Varchar2);

p_address.Direction = ParameterDirection.Input;

p_address.Value = pAddress[i];

command.Parameters.Add(p_address);

OracleParameter p_phone = new OracleParameter("p_phone", OracleDbType.Varchar2);

p_phone.Direction = ParameterDirection.Input;

p_phone.Value = pPhone[i];

command.Parameters.Add(p_phone);

command.ExecuteNonQuery();

command.Parameters.Clear();

}

return true;

}

catch

{

return false;

}

finally

{

command.Dispose();

}

}

Mất tổng thời gian để insert 10000 record là 10.406 giây

Cách 2 dùng store procedure. Trong trường hợp này chúng ta gửi 10000 command đi đi về về yêu cầu insert về cho database server, và câu lệnh đã được biên dịch sẳn.

public static bool SPInsertData(OracleConnection pConnection, string[] pName, string[] pAddress, string[] pPhone)

{

OracleCommand command = new OracleCommand("pac_table2.insert_data", pConnection);

command.CommandType = CommandType.StoredProcedure;

try

{

for (int i = 0; i <>

{

//Bind Parameter

OracleParameter p_name = new OracleParameter("p_name", OracleDbType.Varchar2);

p_name.Direction = ParameterDirection.Input;

p_name.Value = pName[i];

command.Parameters.Add(p_name);

OracleParameter p_address = new OracleParameter("p_address", OracleDbType.Varchar2);

p_address.Direction = ParameterDirection.Input;

p_address.Value = pAddress[i];

command.Parameters.Add(p_address);

OracleParameter p_phone = new OracleParameter("p_phone", OracleDbType.Varchar2);

p_phone.Direction = ParameterDirection.Input;

p_phone.Value = pPhone[i];

command.Parameters.Add(p_phone);

command.ExecuteNonQuery();

command.Parameters.Clear();

}

return true;

}

catch

{

return false;

}

finally

{

command.Dispose();

}

}

Mất tổng thời gian để insert 10000 record là 9.719 giây

Cách 3 dùng Array Binding, ưu điểm của cách này là chúng ta sẽ add parameters cho command, và chỉ một lần gửi yêu cầu tới database server, như vậy chúng ta sẽ đỡ tốn thời gian đi đi về về mỗi lần Execute command. Điểm cần để ý ở đây là command.ArrayBindCount = pName.Length; báo cho database server tiến hành Execute theo số tham số, ví dụ chúng ta cần insert vào 10000 record thông tin liên lạc, thì sẽ add vào 10000 các parameter tương ứng và sẽ gửi 1 lần yêu cầu cho database server. Database server sẽ tiến hành execute 10000 lần store procedure mà chỉ tốn một lần gửi yêu cầu tới.

public static bool ABInsertData(OracleConnection pConnection, string[] pName, string[] pAddress, string[] pPhone)

{

OracleCommand command = new OracleCommand("pac_table3.insert_data", pConnection);

command.CommandType = CommandType.StoredProcedure;

command.ArrayBindCount = pName.Length;

//Bind Parameter

OracleParameter p_name = new OracleParameter("p_name", OracleDbType.Varchar2);

p_name.Direction = ParameterDirection.Input;

p_name.Value = pName;

command.Parameters.Add(p_name);

OracleParameter p_address = new OracleParameter("p_address", OracleDbType.Varchar2);

p_address.Direction = ParameterDirection.Input;

p_address.Value = pAddress;

command.Parameters.Add(p_address);

OracleParameter p_phone = new OracleParameter("p_phone", OracleDbType.Varchar2);

p_phone.Direction = ParameterDirection.Input;

p_phone.Value = pPhone;

command.Parameters.Add(p_phone);

try

{

command.ExecuteNonQuery();

return true;

}

catch

{

return false;

}

finally

{

p_name.Dispose();

p_address.Dispose();

p_phone.Dispose();

command.Dispose();

}

}

Mất tổng thời gian để insert 10000 record là 3 giây

Cách 4 Dùng PL/SQL Associative Arrays. Ưu điểm của cách này hơn Array Binding ở chỗ là đối với Array Binding thì database server sẽ tiến hành execute 10000 lần SP, thì dùng cách này database server sẽ chỉ tiến hành 1 lần execute SP và cũng chỉ mất một lần đi đi về về triệu gọi thực thi command. Điểm cần lưu ý ở đây là sử dụng OracleCollectionType.PLSQLAssociativeArray;

public static bool AAInsertData(OracleConnection pConnection, string[] pName, string[] pAddress, string[] pPhone)

{

OracleCommand command = new OracleCommand("pac_table4.insert_data_asso", pConnection);

command.CommandType = CommandType.StoredProcedure;

//Bind Parameter

OracleParameter p_name = new OracleParameter("p_name", OracleDbType.Varchar2);

p_name.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

p_name.Direction = ParameterDirection.Input;

p_name.Value = pName;

p_name.Size = pName.Length;

command.Parameters.Add(p_name);

OracleParameter p_address = new OracleParameter("p_address", OracleDbType.Varchar2);

p_address.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

p_address.Direction = ParameterDirection.Input;

p_address.Value = pAddress;

p_address.Size = pAddress.Length;

command.Parameters.Add(p_address);

OracleParameter p_phone = new OracleParameter("p_phone", OracleDbType.Varchar2);

p_phone.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

p_phone.Direction = ParameterDirection.Input;

p_phone.Value = pPhone;

p_phone.Size = pPhone.Length;

command.Parameters.Add(p_phone);

try

{

command.ExecuteNonQuery();

return true;

}

catch

{

return false;

}

finally

{

p_name.Dispose();

p_address.Dispose();

p_phone.Dispose();

command.Dispose();

}

}

Mất tổng thời gian để insert 10000 record là 0.578 giây

Bước 4: Select dữ liệu, kiểm tra sự thay đổi thời gian khi thay đổi FetchSize. Như chúng ta đã biết khi select dữ liệu thì databae server sẽ trả về từng gói dữ liệu nhỏ hơn hoặc bằng FetchSize, như vậy việc linh động sử dụng FetchSize thì sẽ cho chúng ta được thời gian select nhu mong muốn. Ví dụ nếu cần càng nhiều dữ liệu sớm thì chúng ta cần FetchSize lớn, hoặc nếu chúng ta chỉ cần show một phần đầu của dữ liệu thì có thể sử dụng FetchSize nhỏ, phần còn lại sẽ được tiếp tục duyệt.

public static ArrayList SPSelectData(OracleConnection pConnection, uint pCountRecords)

{

OracleCommand command = new OracleCommand("pac_table2.select_data", pConnection);

command.CommandType = CommandType.StoredProcedure;

OracleParameter o_cursor = new OracleParameter("o_cursor", OracleDbType.RefCursor);

o_cursor.Direction = ParameterDirection.Output;

command.Parameters.Add(o_cursor);

OracleDataReader reader = null;

try

{

reader = command.ExecuteReader();

ArrayList list = new ArrayList(1000);

//long temSize = command.RowSize * pCountRecords;

long tempSize = 337 * pCountRecords;

//if(tempSize <>

// tempSize = 65536

reader.FetchSize = tempSize;

while (reader.Read())

{

TableInfo info = new TableInfo();

info.ID = reader.GetDecimal(0);

info.NAME = reader.GetString(1);

info.ADDRESS = reader.GetString(2);

info.PHONE = reader.GetString(3);

list.Add(info);

}

if (list.Count > 0)

return list;

else

return null;

}

catch

{

return null;

}

finally

{

if (reader != null)

{

if (!reader.IsClosed)

reader.Close();

reader.Dispose();

}

command.Dispose();

}

}

Lần 1: select 10000 records một lần mất 1.609 giây

Lần 2: select 1000 records một lần mất 1.906 giây

Lần 3: select 1 records một lần mất 6.172 giây

Bài viết về cơ bản ODP.NET tạm dừng tại đây, rất mong nhận được sự đóng góp ý kiến của các bạn để có thể hoàn thiện hơn.




Các bạn tải chi tiết bài viết và mã nguồn chương trình theo link dưới đây.
http://cid-60a6680ce5dc0825.office.live.com/self.aspx/Programing/ODP%5E_NET.rar

Lê Đức Tâm