Delphi:TADoConnection变量赋值的引用与复制

时间:2016-09-23 16:54:50

标签: delphi variable-assignment adoconnection

我试图了解Delphi如何处理任务。我有一个名为GlobalConnTADoConnection)...

的全局连接

我有一个使用传入的变量进行数据库调用的函数:

function MakeDBCall( AConnection : TAdoConnection )
var LocalConn : TAdoConn;
begin
   LocalConn := TAdoConnection.Create(nil);
   try
       LocalConn := AConnection
       ///create the table and perform action using the LocalConn
   finally
       LocalConn.free;    
   end;
end;

将使用MakeDbCallGlobalConn);

进行通话
  1. LocalConn := AConnection(函数内部)实际发生了什么?引用计数是增加还是新副本分配给局部变量?

  2. 释放LocalConn会影响GlobalConn吗?

  3. 理想情况下,我认为制作副本比获取连接字符串更好(更快)并分配给局部变量并打开......这是正确的假设吗?

  4. 这与Delphi 7和XE7-Xe10的处理方式有何不同?

  5. 感谢

1 个答案:

答案 0 :(得分:3)

您的代码没有按照您的想法执行。我已经提出了一些意见,试图解释究竟发生了什么。

function MakeDBCall( AConnection : TAdoConnection )
var 
  LocalConn : TAdoConn;
begin
  // This creates a brand new ADO connection. 
  LocalConn := TAdoConnection.Create(nil);
  try
    // This line discards the connection you've just created, 
    // orphaning it (leaking the memory), and sets LocalConn
    // to point to the object passed in as AConnection.
    LocalConn := AConnection

    ///create the table and perform action using the LocalConn
  finally
    // This line frees AConnection, making your global variable invalid
    LocalConn.free;    
  end;
end;

所以直接处理你提出的问题:

  
      
  1. LocalConn:= AConnection(函数内部)实际发生了什么?引用计数是增加还是新副本分配给本地变量?
  2.   

以上都不是。

分配会丢弃您刚刚创建的全新连接,泄漏已分配的内存,LocalConn成为指向AConnection的新变量,而不是副本。 TADOConnection不是接口,因此不受引用计数的影响。没有分配新副本 - LocalConn只是指向您传递给函数的连接实例的另一个变量。

  
      
  1. 释放LocalConn会影响GlobalConn吗?
  2.   

是。它释放AConnection,使得对它的任何引用都无效,可能是你的全局连接实例。 (它对您使用TADOConnection.Create(nil)创建的本地连接没有任何作用;该内存被泄露,因为您放弃了可用于释放它的唯一引用。

  
      
  1. 理想情况下,我认为制作副本比获取连接字符串更好(更快)并分配给局部变量并打开......这是正确的假设吗?
  2.   

可能是,如果事实上你正在复制,但你不是。

  
      
  1. 这是否与Delphi 7和XE7-Xe10不同?
  2.   

没有。在处理VCL和Windows时,我在上面提到的从v1开始的每个版本的Delphi都是一样的。 (移动设备上的FMX改变了一些东西,但它不会改变你仍然错误地释放全局对象的事实。)

如果TADOConnection实际上实现了Assign方法,则可以使用它。然而,从文档中不清楚它是否已实现;文档链接到TPersistent.Assign。您可以查看您实际使用的Delphi版本的来源(我在这台笔记本电脑上没有D2007),看它是否已实现。如果是,您可以使用以下内容:

LocalConn := TADOConnection.Create(nil);
try
  LocalConn.Assign(AConnection);
  // Use LocalConn
finally
  LocalConn.Free;  // Frees the local copy
end;