2010-02-21 29 views
7

Tôi muốn thực hiện truy vấn cơ sở dữ liệu trong chuỗi nền. Thư viện OmniThread sẽ giúp tôi với tất cả các công cụ chuỗi, nhưng có một điều tôi không hiểu cho đến thời điểm này:Cách truy cập đúng các kết quả truy vấn được tạo trong chuỗi nền?

Mọi luồng đều cần kết nối cơ sở dữ liệu riêng biệt. Chủ đề nền do đó tạo ra kết nối DB, tạo truy vấn và sau đó thực thi nó.

Bây giờ tôi có thể truy cập kết quả truy vấn bằng cách sử dụng đối tượng truy vấn của chuỗi nền.
Nhưng sau khi truy vấn được thực hiện, tôi muốn truy cập kết quả truy vấn trong chuỗi chính chính.

Nếu tôi chỉ đề cập đến đối tượng truy vấn chuỗi nền, điều này có gây ra sự cố không vì tôi đang truy cập kết nối DB trong chuỗi khác?

Như tôi đã hiểu, trong trường hợp này, chuỗi chính sẽ không có kết nối DB riêng biệt và sử dụng kết nối từ chuỗi nền không tốt.

Suy nghĩ của tôi bị méo mó và cách nào phù hợp để làm điều này?

Trả lời

12

Nếu nhiệm vụ OTL của bạn cần phải tải một danh sách sắp xếp của công ty phù hợp với các tiêu chí:

// create and open query to fetch list of companies 
while not qryCompanies.Eof do begin 
    C := TCompany.Create; 
    try 
    C.LoadFromDataset(qryCompanies); 
    Companies.Add(C); 
    except 
    C.Free; 
    raise; 
    end; 
    qryCompanies.Next; 
end; 

C là đối tượng doanh nghiệp của bạn cho một công ty. Nó có thể bởi một đối tượng (TCompany) hoặc một giao diện (ICompany) được thực hiện bởi đối tượng. CompaniesTList<TCompany> hoặc TList<ICompany>. Vào cuối của nhiệm vụ bạn gửi danh sách các công ty để thread VCL:

Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies)); 

Trong hình thức mà bạn muốn hiển thị danh sách các công ty bạn xử lý các sự kiện OnTaskMessage của otlEventMonitor dụ đó là giám sát công việc của bạn :

procedure TListBaseFrame.otlEventMonitorTaskMessage(
    const task: IOmniTaskControl); 
var 
    MsgID: word; 
    MsgValue: TOmniValue; 
begin 
    task.Comm.Receive(MsgID, MsgValue); 
    Assert(MsgValue.IsInterface); 
    if fLoaderTask = task then begin 
    SetLoadedData(MsgID, MsgValue.AsInterface); // or MsgValue.AsObject); 
    fLoaderTask := nil; 
    end; 
end; 

Danh sách công ty thay thế danh sách trước đó và có thể được hiển thị trong lưới.

Tương tự, bạn có thể trả về một đối tượng/giao diện công ty để hiển thị và chỉnh sửa.

Hai điều đó là đáng suy nghĩ về: đối tượng

  • Nếu bạn đã cho đến nay ưa thích để giao diện, viết chương trình đa luồng có thể là một lý do để xem xét lại đó. Nếu bạn tạo các đối tượng của bạn trong một chủ đề nền, sau đó chuyển chúng vào chủ đề VCL và quên chúng trong luồng nền, thì các đối tượng có thể hoạt động tốt. Tuy nhiên, tôi thấy rằng hiệu suất tốt hơn nhiều có thể có bằng cách lưu trữ các đối tượng trong ứng dụng và chỉ tải các bản ghi từ cơ sở dữ liệu chưa được tải hoặc đã thay đổi.Tất cả các bảng của tôi có một chỉ số thay đổi (số nguyên 64 bit, một dấu thời gian có thể hoạt động tốt) gắn liền với nó, được thay đổi với mọi cập nhật. Thay vì thực hiện một

    select * from foo where (...) order by (...) 
    

    tôi chỉ bao giờ thực hiện một

    select id, change_index from foo where (...) order by (...) 
    

    sau đó kiểm tra trong bộ nhớ cache cho dù một đối tượng với cùng id (khóa chính) và chỉ số thay đổi đã tồn tại, nếu có thì trả lại cache đối tượng và chỉ khi không tạo đối tượng kinh doanh mới và tải tất cả các cột. Nhưng nếu bạn lưu trữ các đối tượng, bạn sẽ có tham chiếu đến chúng từ nhiều chủ đề và các vấn đề về quyền sở hữu sẽ trở nên phức tạp đến mức quản lý lâu dài dựa trên số lượng tham chiếu là cách duy nhất để duy trì tính sáng suốt. Sử dụng giao diện thay vì các đối tượng giúp rất nhiều trong vấn đề này.

  • Việc thêm đối tượng đồng bộ hóa vào từng đối tượng kinh doanh là cần thiết, nếu nhiều chủ đề có thể truy cập chúng đồng thời. Đó là tất nhiên có thể, nhưng có thể giới thiệu thêm phức tạp và deadlocks tiềm năng. Nếu bạn thực hiện các đối tượng kinh doanh của bạn như là bất biến, thì không cần khóa nào cả. Tôi đang sử dụng phương pháp đó nhiều hơn và nhiều hơn nữa, và trong khi phải mất một số nhận được sử dụng để nó nó có thể đơn giản hóa mọi thứ rất nhiều.

+0

Hoàn hảo! Đó là chính xác những gì tôi đã mất tích ... cách để có được kết quả qua các chủ đề khác. Cảm ơn bạn rất nhiều! – Holgerwa

+0

+1 câu trả lời tuyệt vời! – jpfollenius

+0

Câu trả lời hay, như thường lệ! – gabr

5

Cách tốt nhất có lẽ là không sử dụng các thành phần nhận biết db trong GUI. Các luồng nên liên lạc với cơ sở dữ liệu và lưu trữ thông tin trong các đối tượng nghiệp vụ, sau đó có thể gửi đến luồng chính (mà sẽ hiển thị chúng).

Đa luồng là khó, không chỉ từ quan điểm triển khai mà còn từ quan điểm của thiết kế ứng dụng. Nó thường là tốt nhất nếu bạn nghĩ về các chủ đề nền như là một lớp riêng biệt với đầu vào và đầu ra được xác định rõ.

+0

"..và lưu trữ thông tin trong đối tượng kinh doanh". Đó là điểm tôi bị kẹt. Tôi không sử dụng bất kỳ thành phần nhận biết dữ liệu nào, tôi chỉ cần lấy dữ liệu kết quả truy vấn đến luồng chính. Bạn coi đối tượng kinh doanh là gì? – Holgerwa

+1

Đối tượng kinh doanh = một thể hiện của lớp chứa dữ liệu từ cơ sở dữ liệu của bạn, được chuyển đổi thành cách lập trình hướng đối tượng (nghĩa là không giống như kết quả SQL nhưng giống như thứ bạn thiết kế trên giấy khi bạn nghiên cứu vấn đề của mình). – gabr

Các vấn đề liên quan