Ta đã thấy giao tác trong db4o làm việc nhƣ thế nào thông qua các khái niệm. Ta chuẩn bị công cụ để thực hiện giao tác.
Pilot pilot = new Pilot("Rubens Barrichello", 99); Car car = new Car("BMW");
car.Pilot = pilot; db.Store(car);
Pilot pilot = new Pilot("Michael Schumacher", 100); Car car = new Car("Ferrari");
car.Pilot = pilot; db.Store(car);
2.2.9.1. Server nhúng
Về phía API, không có sự khác biệt lớn giữa các thực thi đồng thời trên máy ảo và các giao tác thực thi từ một server ở xa. Để sử dụng đồng thời giao tác trên máy ảo, ta mở một server db4o trên file cơ sở dữ liệu, hƣớng nó chạy trên port 0, bằng cách đó thông báo rằng không có mạng nào bị chiếm dụng.
Làm việc ở chế độ này có các đặc điểm sau: Không phân phối qua mạng.
Client và server chạy trên cùng một máy Thực thi tốt hơn cho các ứng dụng nhiều luồng Server bắt đầu trên port 0
Client đƣợc mở bằng cách sử dụng phƣơng thức OpenClient(). // Truy cập tới Server cục bộ
try {
IObjectContainer client = server.OpenClient(); // Thực hiện các công việc
client.Close(); }
finally {
server.Close(); }
Một lần nữa, ta sẽ mở và đóng server để tạo môi trƣờng tƣơng tác với client. // Truy vấn tới Server cục bộ
IObjectContainer client = server.OpenClient(); ListResult(client.QueryByExample(new Car(null))); client.Close();
Mức giao tác trong db4o là uỷ thác đọc (read committed) . Tuy nhiên, mỗi client chứa bộ nhớ đệm duy trì tham chiếu tới các đối tƣợng đã biết. Để tạo ra tất cả sự thay đổi chuyển giao bởi các client khác ngay lập tức, ta phải làm tƣơi các đối tƣợng đã biết từ server. Chúng ta giao phó nhiệm vụ này cho phiên bản của phƣơng thức LISTRESULT()
public static void ListRefreshedResult(IObjectContainer container, IObjectSet items, int depth) {
Console.WriteLine(items.Count); foreach (object item in items) {
container.Ext().Refresh(item, depth); Console.WriteLine(item);
} }
IObjectContainer client1 =server.OpenClient(); IObjectContainer client2 =server.OpenClient(); Pilot pilot = new Pilot("David Coulthard", 98);
IObjectSet result = client1.QueryByExample(new Car("BMW")); Car car = (Car)result.Next();
car.Pilot = pilot; client1.Store(car); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Commit(); ListResult(client1.QueryByExample(typeof(Car))); ListRefreshedResult(client2, client2.QueryByExample(typeof(Car)), 2);
client1.Close(); client2.Close();
Các rollback đơn giản làm việc nhƣ sau.
IObjectContainer client1 = server.OpenClient(); IObjectContainer client2 = server.OpenClient();
IObjectSet result = client1.QueryByExample(new Car("BMW")); Car car = (Car)result.Next();
car.Pilot = new Pilot("Someone else", 0); client1.Store(car); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Rollback(); client1.Ext().Refresh(car, 2); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Close(); client2.Close(); 2.2.9.2. Truy cập qua mạng
Đây chỉ là bƣớc nhỏ để thao tác chuyển db4o trên mạng thông qua giao thức TCP/IP. Ta định rõ số cổng lớn hơn 0 và thiết lập một hoặc nhiều account cho các client.
Client mở kết nối TCP/IP tới server sử dụng các phƣơng thức: Phƣơng thức 1: Db4oFactory.OpenServer(YapFileName, ServerPort);
Phƣơng thức 2: Db4oFactory.OpenClient("localhost", ServerPort, ServerUser, ServerPassword)
Client gửi các yêu cầu truy vấn, chèn, cập nhật, xoá tới server và nhận dữ liệu từ server
// Truy cập tới Server từ xa
IObjectServer server = Db4oFactory.OpenServer(YapFileName, ServerPort);
server.GrantAccess(ServerUser, ServerPassword); try {
IObjectContainer client = Db4oFactory.OpenClient("localhost", ServerPort, ServerUser, ServerPassword);
// Thực hiện các công việc client.Close();
}
finally {
server.Close(); }
Client kết nối thông qua host, port, user name và password. // Truy vấn tới Server từ xa
IObjectContainer client = Db4oFactory.OpenClient("localhost", port, user, password);
ListResult(client.QueryByExample(new Car(null))); client.Close();
Mọi thao tác khác tƣơng tự nhƣ các ví dụ trên.
IObjectContainer client1 = Db4oFactory.OpenClient("localhost", port, user, password);
IObjectContainer client2 = Db4oFactory.OpenClient("localhost", port, user, password);
Pilot pilot = new Pilot("Jenson Button", 97);
IObjectSet result = client1.QueryByExample(new Car(null)); Car car = (Car)result.Next();
car.Pilot = pilot; client1.Store(car); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Commit(); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Close(); client2.Close();
IObjectContainer client1 = Db4oFactory.OpenClient("localhost", port, user, password);
IObjectContainer client2 = Db4oFactory.OpenClient("localhost", port, user, password);
IObjectSet result = client1.QueryByExample(new Car(null)); Car car = (Car)result.Next();
car.Pilot = new Pilot("Someone else", 0); client1.Store(car); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Rollback(); client1.Ext().Refresh(car,2); ListResult(client1.QueryByExample(new Car(null))); ListResult(client2.QueryByExample(new Car(null))); client1.Close(); client2.Close();
2.2.9.3. Dải tín hiệu
Thỉnh thoảng, một client cần gửi thông báo đặc biệt tới server với mục đích bảo server làm một việc gì đó. Server có thể cần tín hiệu thực thi chắp nối (defragment) hoặc có thể cần tín hiệu để tự tắt nó. Điều này đƣợc cấu hình bằng cách gọi phƣơng thức SETMESSAGERECIPIENT(), qua đó đối tƣợng sẽ xử lý thông điệp từ client.
public void RunServer() { lock(this)
{
IObjectServer db4oServer = Db4oFactory.OpenServer(FILE, PORT); db4oServer.GrantAccess(USER, PASS); db4oServer.Ext().Configure().ClientServer().SetMessageRecipient(this); try { if (! stop) { Monitor.Wait(this); } } catch (Exception e) { Console.WriteLine(e.ToString()); } db4oServer.Close(); } }
Thông điệp đƣợc nhận và xử lý bởi phƣơng thức PROCESSMESSAGE(): public void ProcessMessage(IMessageContext con, object message) { if (message is StopServer) {
Close(); }
}
Db4o cho phép một client gửi một tín hiệu tuỳ ý hoặc một thông điệp tới server bằng cách gửi một đối tƣợng thuần tuý đến server. Server sẽ nhận đƣợc một thông điệp chứa đối tƣợng đến từ client. Server có thể hiểu thông điệp này.
public static void Main(string[] args) { IObjectContainer IObjectContainer = null; try {
IObjectContainer = Db4oFactory.OpenClient(HOST, PORT, USER, PASS);
}
catch (Exception e) {
}
if (IObjectContainer != null) {
IMessageSender messageSender = IObjectContainer.Ext() .Configure().ClientServer().GetMessageSender(); messageSender.Send(new StopServer()); IObjectContainer.Close(); } } 2.3. Kết luận
Chƣơng này đã trình bày các thao tác với hệ quản trị db4o nhƣ: mở cơ sở dữ liệu, lƣu trữ, xóa, cập nhật, làm việc ở chế độ đơn và Client/Server,…Để thấy rõ ứng dụng của cơ sở dữ liệu hƣớng đối tƣợng, ta sẽ tìm hiểu thông qua chƣơng trình ở chƣơng tiếp theo.
Chƣơng 3
BÀI TOÁN QUẢN LÝ SINH VIÊN KHOA CÔNG NGHỆ THÔNG TIN TRƢỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI