2012-02-08 34 views
5

Tôi đã đọc một bài đăng trên blog (tại thời điểm này tôi không thể tìm thấy liên kết), nơi tác giả đã nói nhanh hơn để gán biến cục bộ hơn sử dụng ADOQuery.FieldByName (' ... '). asString hoặc TSQLQuery.FieldByName (' ... '). asString, khi phân tích cú pháp toàn bộ truy vấn với hàng nghìn bản ghi. Tôi không thấy sự khác biệt giữaDelphi - FieldByName.AsString - thực hành tốt

var aLocalField: TField; 
.... 
aLocalField := ADOQuery.FieldByName('...'); 
.. 
ShowMessage(aLocalField.asString) 

và bằng cách sử dụng trực tiếp

ShowMessage(ADOQuery.FieldByName('...').asString); 

Blog bài không nói bất cứ điều gì về kiểu cơ sở dữ liệu hoặc phiên bản Delphi. Là giải pháp này liên quan đến một hoặc khác (và tôi không nói về hệ thống cơ sở dữ liệu tùy biến/tối nghĩa)?

+4

Hai bit mã sẽ thực hiện hệt. –

+1

Bạn có thể liên kết bài đăng đó không? Có lẽ bạn đã hiểu lầm điều gì đó. – CodesInChaos

+0

Tôi đoán có thể nhanh hơn nếu bạn cần truy cập cùng một giá trị nhiều lần (vì vậy thay vì gọi 'FieldByName' nhiều lần bạn sử dụng biến) – a1ex07

Trả lời

17

Không có sự khác biệt hiệu suất đáng chú ý giữa hai. Tôi hy vọng những gì bạn tìm thấy là sự khác biệt giữa

DataSet.First; 
while not DataSet.Eof do 
begin 
    ProcessValue(DataSet.FieldByName('Field').AsString); 
    DataSet.Next; 
end; 

so

Field := DataSet.FieldByName('Field'); 
DataSet.First; 
while not DataSet.Eof do 
begin 
    ProcessValue(Field.AsString); 
    DataSet.Next; 
end; 

Nếu vậy, sau này là hiệu quả hơn vì FieldByName là một (tương đối) chức năng chậm. Nếu bạn không cần gọi nhiều lần, đừng gọi nhiều lần.

+1

_Nếu bạn không cần phải gọi nó nhiều lần, đừng gọi nó nhiều hơn một lần._ Nghe! Nghe! –

+1

_ sau này hiệu quả hơn ..._ IMO cũng dễ đọc, gỡ lỗi và bảo trì hơn. –

+2

điều cần biết. btw của nó năm 2012 và vẫn không có iterator cho tập dữ liệu, bệnh chỉ cần chờ đợi thêm 10 năm. – none

5

Điều gì làm cho cảm giác này là:

  1. Nếu bạn có một CLASS (chẳng hạn như một TForm) không phải là một chức năng địa phương, bạn có kiên trì tạo ra các lĩnh vực bạn tránh được những chi phí tra cứu lặp đi lặp lại (FieldByName).

  2. Nếu bạn không sử dụng trường liên tục (trong dfm), bạn có thể thực hiện tra cứu một lần trong thời gian chạy và tránh chi phí liên tục tìm kiếm, nếu nó được sử dụng hoặc (a) nhiều lần ngữ cảnh của một hàm duy nhất, hoặc (b) nơi nó có thể được tra cứu một lần khi truy vấn được thực hiện và được lưu trữ trong một trường được bảo vệ của một đối tượng, để nó có thể được sử dụng lại cho truy vấn hoặc đối tượng, như là thích hợp.

Ví dụ giả mạo của bạn không có lợi, nhưng tôi tin rằng tra cứu lặp lại các trường khi tra cứu lôgic lặp lại bị lãng phí, có lẽ là một điều đáng để đề cập là "lãng phí".

tôi thấy mã như thế này cả ngày, và nó khiến tôi phát điên:

procedure TSomething.DoSomething; 
begin 
    fDataset.FieldByName('X').AsString = fDataset.FieldByName('X').AsString+'Y'; 
end; 

Đoạn mã trên được thực hiện ít có thể đọc được bởi lặp đi lặp lại như vậy, và mối quan tâm có thể đọc như vậy, cũng như kiểm tra lỗi mối quan tâm là tại sao tôi sẽ tránh được việc trên, và thay vào đó có một trường fX:TField:

TSomething = class(TBaseClass) 
    protected 
    fDataSet:TDataSet; 
    fX:TField; 

end; 

Bây giờ chúng ta có thể viết

fX.AsString := fX.AsString + 'Y'; 

Tôi nghĩ mọi người lo lắng quá nhiều về Hiệu suất và không đủ về chất lượng, và biểu hiện nhanh lặp đi lặp lại là dấu hiệu "thiếu chất lượng" và "thiếu suy nghĩ" cũng giống như "thiếu quan tâm đến hiệu suất".

+0

_Tôi thấy mã như thế này cả ngày, và nó khiến tôi khốn khổ._ Than ôi, bạn không đơn độc ... –

+1

Hi Warren: +1. Những gì bạn gọi là các lĩnh vực tĩnh là tôi nghĩ rằng được gọi là lĩnh vực liên tục (vì các lĩnh vực được lưu giữ trong dfm như trái ngược với IDE quên chúng tất cả các thời gian :-) –

+0

Cảm ơn Marjan. Đã sửa. –

1

FieldByName sử dụng tìm kiếm đơn giản. nếu bạn muốn chọn nhiều hơn một trường. mã này là tốt hơn

// Same Text in StrUtils(unit) 
for I:=0 to DataSet.Fields.Count-1 do 
begin 
    if SameText(DataSet.Fields[I].FieldName,'Field1') then 
    Field1:=DataSet.Fields[I] 
    else if SameText(DataSet.Fields[I].FieldName,'Field2') then 
    Field2:=DataSet.Fields[I]; 
end; 
DataSet.First; 
while not DataSet.Eof do 
begin 
    ProcessValue(Field.AsString); 
    DataSet.Next; 
end;