này Bằng cách loại bỏ các xử lý ngoại lệ, bạn đang làm tê liệt RAII của bạn.
Mã nên được
try
{
DBTransaction trans(db) ;
// Lots of DELETE and INSERT
// should one fail, a DBTransactionRollback exception will be thrown
trans.commit() ;
}
catch(const DBTransactionRollback & e)
{
// If really needed, you could extract failure information from "e"
}
Sự khác biệt với mã ban đầu của bạn là những gì thúc đẩy câu trả lời của tôi:
Không có gì cần thiết trong "bắt" là: Destructor sẽ đảm nhận một tự động rollback trừ khi phương thức commit() được gọi thành công (, ví dụ, có thể thiết lập một số thành viên boolean riêng của DBTransaction thành true). Việc nắm bắt là nơi mã sẽ tiếp tục, giả sử giao dịch không thành công.
Bạn nên tạo ngoại lệ chuyên dụng (Tôi đặt tên nó là DBTransactionRollback) để ném khoảnh khắc xảy ra lỗi trong một trong các lệnh của bạn. Do đó, hoạt động đánh bắt sẽ chỉ bắt ngoại lệ có động cơ quay ngược lại và không ngoại lệ khác (như STL, v.v.)
Việc sử dụng cơ chế ngoại lệ cho phép bạn đặt mã của mình bằng nhiều chức năng, được gọi từ lần thử này/bắt khối mã, mà không cần phải đối phó với trả về boolean và trả về mã lỗi khác.
Hy vọng điều này sẽ trả lời câu hỏi của bạn.
+1 Đó là cách thực hiện những việc như vậy. Có một vấn đề mặc dù: nếu bạn quên gọi cam kết()? – sharptooth
Và nếu bạn quên tạo biến giao dịch thì sao? Bạn không thể ngăn chặn tất cả các sai lầm. –
@sharptooth: nếu bạn quên thực hiện thay đổi mà bạn muốn cam kết ngay từ đầu thì sao? Tôi không nghĩ bạn có thể làm gì để bảo vệ chống lại sự bất lực. – jalf