“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
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
///
///
///
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
///
///
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
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.
5 comments:
Dài quá, đọc không nổi
http://www.oracle.com/technetwork/topics/dotnet/whatsnew/oracle-entity-framework-sod-130214.pdf
Viết step by step cho những người begin mà. ^^
Thank lớn!
Có phải xml làm nhiệm vụ tạo dữ liệu, rồi sử dụng dữ liệu ấy để chèn vào database và sau đó từ database đưa lên form không? Mình đã tạo được dblink và muốn select để tìm kiếm ở local db và remote db, tức là nếu không tìm thấy ở db này thì tìm ở db kia. Mình có thể sử dụng cursor trong procedure được không và mình phải viết nó thế nào? À, mà khi thực thi 1 khối câu lệnh nào đó trong sql developer có nhất thiết phải bôi đen toàn bộ câu lệnh đó hay không? Cảm ơn bạn đã quan tâm.
Post a Comment