【问题标题】:Refresh ADO dataset when underlying table is updated更新基础表时刷新 ADO 数据集
【发布时间】:2012-07-13 09:09:37
【问题描述】:

是否有可能让ADO Dataset“知道”基础表是否已更新或何时更新?

目前,每次收到文件夹中该项目的文件时,我都必须检查该项目的状态。这会导致大量的 sql 查询,因为我们一次最多可以处理 1300 个事件。

我正在考虑将ADO Dataset 添加到保存状态的应用程序中,并使用Locate 来检查状态。

我希望dataset 在基础表记录发生更改后立即更新,而不是使用计时器进行定期刷新。

谢谢。

【问题讨论】:

    标签: delphi dataset ado


    【解决方案1】:

    ADO 数据集基于客户端/服务器概念将数据检索到客户端。就像一个网络浏览器。

    这意味着:客户端请求 -> 服务器,服务器应答 -> 客户端。所以客户端真的无法知道是否有任何数据被改变了。

    最简单的方法是重新查询数据(关闭/打开)并根据您的需要获取数据,而不是一次全部 1300 个。这是最常用的解决方案。

    无论如何,如果数据量真的很大并且你想优化你有两种方法:

    A.使用触发器构建日志表并注册表数据更改。定期向服务器请求更改(您可以在 background thread 中执行此操作):

    select L.RECORD_ID, L.OPERATION_ID
    from FILE_LOG L
    where L.FDATESTAMP between :LAST_WATCH and :CURRENT_STAMP and L.FOLDER_ID = :FOLDER_ID
    

    您将获得 RECORD_ID 和 OPERATION_ID(即插入/更新/删除)。

    B.如果你没有链接到 DBMS,Firebird/Interbase 有 events 的概念。使用触发器,您可以通知客户端数据已更改,并且您可以重新查询刚刚修改的数据。

    【讨论】:

    • 我喜欢选项 B,因为我会响应由事件表上的触发器触发的数据库事件,而不必定期检查是否有变化。感谢您的想法!
    【解决方案2】:

    据我们所知,SQL Server 中只有一种方法可以检测是否对表进行了任何更改,即使用动态管理视图 sys.dm_db_index_usage_stats (http://msdn.microsoft.com/en-us/library/ms188755.aspx)。

    出于我的目的,我创建了一个函数来更轻松地访问信息。

    create function [dbo].[_efnLastTableUpdateTime](@TableName varchar(255))
    /*  Function to return the last datetime that a table was modified.
        Note that because this is from a dynamic management view, it is only
        since the server was started, i.e. will return null if no change since
        the server was started.
        SQL2005 or later.
    */
    returns datetime
    as
    begin
        declare @Result datetime
        set @Result = (
                select top 1 [last_user_update]
                from sys.dm_db_index_usage_stats
                where object_id=object_id(@TableName)
                order by [last_user_update] desc
            )
        return @Result
    end
    GO
    

    然后我在 TADOQuery 的后代中构建了一个访问它的函数和一个打开或关闭功能的属性。然后我可以按需调用它,这会产生非常有效的响应。

    function TMyADOQuery.HasBeenUpdatedSinceOpen(const ACloseIfHasBeen: boolean = false): boolean;
    const
      sSelectTableUpdateTime = 'select [dbo]._efnLastTableUpdateTime(''%s'')';
    var
      NewUpdateTime: TDateTime;
    begin
      Result := false;
      if(_TrackUpdated) and (Active) and (_TableName > '') then begin
        NewUpdateTime := TrackUpdateQuery.SelectScalarDate(Format(sSelectTableUpdateTime, [_TableName]), 0);
        Result := (FLastUpdateTime <> NewUpdateTime);
        FLastUpdateTime := NewUpdateTime;
      end;
      if(Result) and (ACloseIfHasBeen) then
        Close;
    end;
    

    TrackUpdateQuery 是内部创建的另一个 TADOQuery 实例,SelectScalarDate 是我的 TADOQuery 类的扩展。

    请注意,用户必须拥有VIEW SERVER STATE 权限才能访问管理视图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 2016-09-14
      • 1970-01-01
      • 2012-04-25
      相关资源
      最近更新 更多