Вопрос

Логирование детали Файлы

Здравствуйте!

Понадобилось добавить логирование для детали Файлы.
Включила логирование для нужной таблицы. В деталь Файлы рядом добавила еще грид, который отображает историю.
Проблема обнаружилась вот в чем:
В таблице логирования есть поле ActionID(строка), которое содержит записи вида D и U.
D - добавление, U - изменение и удаление.
Но мне нужно изменение и удаление все-таки различать.
Это можно сделать как-то стандартными средствами?

У нас уже есть подобная реализация для другой детали, там у поля ActionID стоит тип уникального идентификатора.
Для него заведен enm.
Далее, в датасет детали ловятся события добавление\удаление\изменение и в датасет лога, в поле ActionID записывается нужное значение enm. Проблема решена.

Я пыталась поступить точно так же, но у датасет детали Файл - ds_FileInItem не срабатывают события на изменение и добавление. Только на удаление.
Я предполагаю, что это из-за того, что значения вставляются отдельным инсертом.

Подскажите, пожалуйста, что тут можно сделать?

У меня такой же вопрос

7 комментариев

Может update для tbl_Files решит вопрос ? :wink:
Какая версия исполняемых файлов на Вашей машине?

Версия 3.3.2.47
Terrasoft Sales

Игорь, а что вы имеете ввиду под апдейтом tbl_Files?
Поле ActionID хранится только в таблицах логов и содержимое там стандартное, на сколько я понимаю.

Светлана,

Дело в том, что есть бага в хранимой процедуре, которая генерирует триггера к таблицам.
Мы об этой проблеме сообщали команде, которая внедряла нам Террасофт (из самого Террасофта).

Действительно, по-идее должно быть следующее:
I - вставка (Insert)
U - обновление (Update)
D - удаление (Delete)

Есть:
D - вставка
U - обновление
D - удаление

komgbu,

а вам эту багу еще не исправили?

Светлана,

Нет, не исправили, у нас много других более критичных проблем, помимо этой :)
Я думаю стоит подождать, пока ответят разработчики из Террасофт в этой ветке.

Здравствуйте,
В хранимой процедуре tsp_TableTrigger поменяйте строчку 306

 '    ,''D'' as [ActionID]' + @NL + 

на

 '    ,''I'' as [ActionID]' + @NL + 

и пересохраните таблицу, что бы пересоздались тригерра.

Проверял на tbl_ContactLog, все работает корректно
1
В итоге хранимая процедура будет иметь вид:

--USE [XRMDistri_Demo_RUS_3_3_2_172]
GO
/****** Object:  StoredProcedure [dbo].[tsp_TableTrigger]    Script Date: 12/12/2011 10:40:06 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[tsp_TableTrigger]
  @ATableName sysname,
  @TrackFieldsInfo varchar(8000),
  @TrackFieldsInfoForDelete varchar(8000),
  @ATrackChangesEnabled int = 1,
  @AClosingPeriodEnabled int = 0,
  @ADBSchema sysname = 'dbo'
as
begin
  set nocount on
------------------- declare -------------------------
 
  declare @SchemaTableName sysname
  declare @TableName sysname
  declare @TableLogName sysname
  declare @ShortTableName sysname
  declare @InteadOfInsertTriggerName sysname
  declare @UpdateTriggerName sysname
  declare @DeleteTriggerName sysname
  declare @UpdateTriggerNameOld sysname
  declare @DeleteTriggerNameOld sysname
  declare @NL sysname
  declare @Column varchar(150)
  declare @LookupColumn varchar(150)
  declare @Line int
  declare @CheckReplication varchar(250)
  declare @DisplayColumn varchar(33)
  declare @SchemaJoinTable varchar(70)
  declare @JoinTable varchar(33)
  declare @JoinField varchar(33)
  declare @DBName sysname  
  declare @RecordTitle varchar(40)
  declare @TableID varchar(36)
  declare @Comma varchar(10)
  declare @Version int
  declare @Trigger2005 varchar(8000)
  declare @DatabaseLogBegin varchar(1000)
  declare @ContactID varchar(1000)
  declare @InsertTableLogBegin varchar(1000)
  declare @DBErrorMessageBegin nvarchar(10)
  declare @DBErrorMessageEnd nvarchar(10)
  declare @IsAdministratedByRecords varchar(10)
 
---------------- clear old triggers -----------------
 
  set @IsAdministratedByRecords = 
    (select Upper(p.Value) from tbl_Service s left outer join tbl_ServiceProperty p on s.id = p.ServiceID
      where s.Code = @ATableName and p.Name = 'IsAdministratedByRecords');
 
  set @TableName = '[' + @ATableName + ']'  
  set @InteadOfInsertTriggerName = '[' + @ADBSchema + '].[tr_' + @ATableName + '_II]'
  set @UpdateTriggerName = '[' + @ADBSchema + '].[tr_' + @ATableName + '_IU]'
  set @DeleteTriggerName = '[' + @ADBSchema + '].[tr_' + @ATableName + '_ID]'
 
  if (not object_id(@InteadOfInsertTriggerName, 'TR') is null)
  begin
    exec('DROP TRIGGER ' + @InteadOfInsertTriggerName)
  end  
  if (not object_id(@UpdateTriggerName, 'TR') is null)
  begin
    exec('DROP TRIGGER ' + @UpdateTriggerName)
  end
  if (not object_id(@DeleteTriggerName, 'TR') is null)
  begin
    exec('DROP TRIGGER ' + @DeleteTriggerName)
  end  
 
  if ((not isnull(@ATrackChangesEnabled, 0) = 1) and 
	(not isnull(@AClosingPeriodEnabled, 0) = 1))
  begin
    exec tsp_CreateDeleteTrigger 
      @Table = @ATableName,
      @IsTrackChanges = 0,
	    @UseClosingPeriod = 0
    return
  end
---------------- initialization ---------------------
 
  set @SchemaTableName = '[' + @ADBSchema + '].' + @TableName  
  set @TableLogName = '[' + @ADBSchema + '].[' + @ATableName + 'Log]'  
  set @ShortTableName = replace(@ATableName, 'tbl_', '')
 
  set @DBName = db_name()
  set @NL = char(13) + char(10)
  set @CheckReplication = 
    '  IF (SYSTEM_USER = ''TS_REPLICATION'') RETURN ' + @NL
  set @TableID = (
    select top 1 [ID] from [tbl_Service] [S]
    where [S].[Code] = @ATableName)
 
  if (@TableID is null) 
  begin
    RAISERROR ('Can''t track changes for new table', 16, 1)
    return
  end
 
  if (@AClosingPeriodEnabled = 1)
  begin
    set @DBErrorMessageBegin = '<#'
    set @DBErrorMessageEnd = '#>'
 
    declare @QuerySQLText nvarchar(4000)
    declare @ClosedPeriodMessage nvarchar(270)
    select
          @ClosedPeriodMessage = replace(@DBErrorMessageBegin + 
						[ClosedPeriodMessage] + @DBErrorMessageEnd, '%', '%%')
    from [tbl_PreventEditing] where [RootTableID] = @TableID     
    set @QuerySQLText = [dbo].[fn_GetClosingPeriodCheckSQL](@TableID)    
 
    declare @UpdateCheckSQLText nvarchar(4000)
    set @UpdateCheckSQLText = @QuerySQLText    
  end 
 
  create table #Trigger ( 
    [Line] int not null identity(1, 1), 
    [Trigger_Text] nvarchar(4000)
  )
 
  create table #TrackFields ( 
    [Line] int not null identity(1, 1), 
    [TrackField] varchar(8000)
  )
 
  insert into #TrackFields ([TrackField])
  select [Part] from [fn_ParseString](@TrackFieldsInfo, ';')
  order by [Line]
 
  set @RecordTitle = ''''''
  set @Line = (select top 1 [Line] from #TrackFields)
  select @Column = [TrackField] from #TrackFields where [Line] = @Line
  if ((@Column is not null) and (@Column <> '') and (@Column <> '...'))  
     set @RecordTitle = '[D].[' + @Column + ']'
  delete from #TrackFields where [Line] = @Line  
 
  set @Version = @@microsoftversion /0x01000000
 
  if (@Version > 8)   
  begin
    set @Trigger2005 =
	    'declare @TriggerText nvarchar(max) ' + @NL + 
	    'set @TriggerText = '''' ' + @NL + 
      'declare @TriggerRec nvarchar(max) ' + @NL +
      'set @TriggerRec = '''' ' + @NL +
      'declare [c] cursor for ' + @NL +
      '  select [Trigger_Text] from #Trigger order by [Line] ' + @NL +
      'open [c] ' + @NL +
      'while (1 = 1) ' + @NL +
      'begin ' + @NL +
      '  fetch next from [c] into @TriggerRec ' + @NL +
      '  if @@fetch_status = -1 break ' + @NL +
      '  if @@fetch_status = -2 continue   ' + @NL +
      '  set @TriggerText = @TriggerText + @TriggerRec ' + @NL +
      'end ' + @NL +
      'close [c] ' + @NL +
      'deallocate [c] ' + @NL +
      'exec (@TriggerText)' 
  end
 
  set @ContactID = @NL +  
    '  declare @ContactID uniqueidentifier' + @NL +
    '  declare @UserIsAdmin int' + @NL +
    '  select @ContactID = au.UserContactID, ' + @NL +
    '         @UserIsAdmin = au.UserIsAdmin ' + @NL +
    '    from tbl_AdminUnit au' + @NL +
    '  where au.SQLObjectName = system_user' + @NL + @NL
 
  set @DatabaseLogBegin =
    '  insert into [tbl_DatabaseLog]' + ' (' + @NL + 
    '    [TableID]' + @NL +
    '    ,[RecordID]' + @NL +
    '    ,[RecordTitle]' + @NL +
    '    ,[ActionID]' + @NL +
    '    ,[CreatedOn]' + @NL +
    '    ,[CreatedByID]' + @NL +
    '  ) ' + @NL
 
------------ instead of update ----------------------
 
  declare @AdministratedByRecords varchar(10)
  set @AdministratedByRecords = 
    (select Upper(p.Value) from tbl_Service s left outer join tbl_ServiceProperty p on s.id = p.ServiceID
      where s.Code = @ATableName and p.Value = 'True'
        and p.Name = 'IsAdministratedByRecords')
 
  exec tsp_CreateUpdateTrigger
    @ADBSchema = @ADBSchema,
    @ATableName = @ATableName,
    @IsTable = 1,
    @AClosingPeriodEnabled = @AClosingPeriodEnabled,
    @AdministratedByRecords = @AdministratedByRecords,
    @ATrackChangesEnabled = @ATrackChangesEnabled,
    @TableLogName = @TableLogName,
    @TrackFieldsInfo = @TrackFieldsInfo,
    @TrackFieldsInfoForDelete = @TrackFieldsInfoForDelete
  if (@AdministratedByRecords = 'TRUE')
  begin
    exec tsp_CreateUpdateTrigger
      @ADBSchema = @ADBSchema,
      @ATableName = @ATableName,
      @IsTable = 0,
      @AClosingPeriodEnabled = @AClosingPeriodEnabled,
      @AdministratedByRecords = @AdministratedByRecords,
      @ATrackChangesEnabled = @ATrackChangesEnabled,
      @TableLogName = @TableLogName,
      @TrackFieldsInfo = @TrackFieldsInfo,
      @TrackFieldsInfoForDelete = @TrackFieldsInfoForDelete
  end
 
------------ instead of delete ----------------------
 
  exec tsp_CreateDeleteTrigger 
    @Table = @ATableName,
    @IsTrackChanges = @ATrackChangesEnabled,
	  @UseClosingPeriod = @AClosingPeriodEnabled,
    @RecordTitle = @RecordTitle,
    @DBSchema = @ADBSchema
 
------------ instead of insert ----------------------
if ((@AClosingPeriodEnabled = 1) or (@ATrackChangesEnabled = 1))
begin
  delete from #Trigger
  insert into #Trigger ([Trigger_Text]) select  
    'create trigger ' + @InteadOfInsertTriggerName + ' on ' + @SchemaTableName + @NL +
    'instead of insert' + @NL + 
    'as' + @NL + 
    '  set nocount on' + @NL 
 
  if (@AClosingPeriodEnabled = 1)
  begin
    declare @InsertCheckSQLText nvarchar(4000)
    set @InsertCheckSQLText = @QuerySQLText    
    set @InsertCheckSQLText = replace(@InsertCheckSQLText, @SchemaTableName, '[inserted]')
    insert into #Trigger ([Trigger_Text]) select @NL +
      '  declare @DenyRecordsCount int ' + @NL +
      '  set @DenyRecordsCount = 0 ' + @NL + 
      '  SELECT ' + @NL +
      '      @DenyRecordsCount = count(*) ' + @NL + @InsertCheckSQLText + @NL + @NL +
      '  if (@DenyRecordsCount > 0) ' + @NL +
      '  begin ' + @NL +
      '    RAISERROR(''' + isnull(@ClosedPeriodMessage, '') + ''', 16, 1) ' + @NL +
      '    return ' + @NL +
      '  end ' + @NL
  end
 
  insert into #Trigger ([Trigger_Text]) select @NL +
    '  insert into ' + @SchemaTableName + ' select * from [inserted]'
 
  if (@ATrackChangesEnabled = 1)
  begin
    insert into #Trigger ([Trigger_Text]) select @NL + 
      @ContactID +
      '  insert into ' + @TableLogName + ' (' + @NL +
      '    [RecordID]' + @NL +
      '    ,[ActionID]' + @NL +
      '    ,[CreatedOn]' + @NL +
      '    ,[CreatedByID]'    
 
    delete from #TrackFields
    insert into #TrackFields ([TrackField])
    select [Part] from [fn_ParseString](@TrackFieldsInfoForDelete, ';')  
    order by [Line]
 
    declare [c1] cursor for
      select [TrackField] from #TrackFields
      order by 1
 
    open [c1]
    while (1 = 1)
    begin    
      fetch next from [c1] into @Column
      if @@fetch_status = -1 break
      if @@fetch_status = -2 continue
 
      if (patindex('%,%', @Column) > 0) 
      begin 
        declare [c2] cursor for
        select [Part] from [fn_ParseString](@Column, ',')
        order by [Line]
 
        open [c2]
        fetch next from [c2] into @Column
        fetch next from [c2] into @DisplayColumn
        close [c2]
        deallocate [c2]
 
        insert into #Trigger ([Trigger_Text])
        select @NL + '    ,[' + @DisplayColumn + ']'
      end
      insert into #Trigger ([Trigger_Text])
      select @NL + '    ,[' + @Column + ']'
    end
    close [c1]
    deallocate [c1]
 
    insert into #Trigger ([Trigger_Text]) select @NL + 
      '  ) ' + @NL + 
      '  select' + @NL + 
      '    [D].[ID] as [RecordID]' + @NL +
      '    ,''I'' as [ActionID]' + @NL + 
      '    ,getdate() as [CreatedOn]' + @NL +
      '    ,[D].[ModifiedByID] as [CreatedByID]'
 
    declare [c1] cursor for
      select [TrackField] from #TrackFields
      order by 1
 
    open [c1]
    while (1 = 1)
    begin
      fetch next from [c1] into @Column
      if @@fetch_status = -1 break
      if @@fetch_status = -2 continue
      if (patindex('%,%', @Column) > 0) 
      begin      
        declare [c2] cursor for
        select [Part] from [fn_ParseString](@Column, ',')
        order by [Line]
 
        open [c2]
        fetch next from [c2] into @Column
        fetch next from [c2] into @DisplayColumn
        fetch next from [c2] into @JoinTable
        fetch next from [c2] into @JoinField
 
        set @DisplayColumn = '[' + @DisplayColumn + ']'
        set @JoinTable = '[' + @JoinTable + ']'
        set @SchemaJoinTable = '[' + @ADBSchema + '].' + @JoinTable
        set @JoinField = '[' + @JoinField + ']'
 
        close [c2]
        deallocate [c2]
 
        insert into #Trigger ([Trigger_Text]) select @NL +
          '   ,(select ' + @JoinTable + '.' + @JoinField + @NL +
          '      from ' + @SchemaJoinTable + ' as ' + @JoinTable + @NL +
          '      where  ' + @JoinTable + '.[ID] = [D].[' + @Column + '])' + @NL + 
          '    as ' + @DisplayColumn
      end 
 
      insert into #Trigger ([Trigger_Text])
      select @NL + '    ,[D].[' + @Column + '] as [' + @Column + ']'
    end
    close [c1]
    deallocate [c1]
 
    insert into #Trigger ([Trigger_Text]) select @NL + 
      '  from [INSERTED] AS [D] ' + @NL
 
    insert into #Trigger ([Trigger_Text]) select @NL + 
      @DatabaseLogBegin +
      '  select' + @NL + 
      '    ''' + @TableID + ''' as [TableID]' + @NL + 
      '    ,[D].[ID] as [RecordID]' + @NL + 
      '    ,' + @RecordTitle + ' as [RecordTitle]' + @NL + 
      '    ,''I'' as [ActionID]' + @NL + 
      '    ,getdate() as [CreatedOn]' + @NL +
      '    ,@ContactID as [CreatedByID]' + @NL +    
      '  from [INSERTED] AS [D]' 
  end
 
  if (@Version = 8)
    exec master.dbo.xp_execresultset 'select [Trigger_Text] from #Trigger order by [line]', @DBName
  else
    exec (@Trigger2005)
end
end
drop table #TrackFields
drop table #Trigger

Алексей, все получилось, спасибо! :)

Войдите или зарегистрируйтесь, чтобы комментировать