Announcement

Collapse
No announcement yet.

CLR Trigger

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • CLR Trigger

    Hallo Experten,

    bei der Integration eines CLR Triggers bekomme ich bei der Aktivierung folgende Fehlermeldung:

    Der Trigger wird nach einem INSERT aktiv.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Meldung 6522, Ebene 16, Status 1, Prozedur CLRTrigger, Zeile 1
    .NET Framework-Fehler beim Ausführen der benutzerdefinierten Routine oder des benutzerdefinierten Aggregats "CLRTrigger":
    System.Security.HostProtectionException: Attempted to perform an operation that was forbidden by the CLR host.

    The protected resources (only available with full trust) were: All
    The demanded resources were: UI

    System.Security.HostProtectionException:
    at System.Security.CodeAccessSecurityEngine.ThrowSecu rityException(Assembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed)
    at System.Security.CodeAccessSecurityEngine.ThrowSecu rityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed)
    at System.Security.CodeAccessSecurityEngine.CheckSetH elper(PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Object assemblyOrString, SecurityAction action, Boolean throwException)
    at System.Security.CodeAccessSecurityEngine.CheckSetH elper(CompressedStack cs, PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Assembly asm, SecurityAction action)
    at CLRTrigger.CLRTriggers.DropTableTrigger()
    .
    Die Anweisung wurde beendet.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Kann jemand mir helfen, bzw. welche Sicherheitseinstellung kann ich konfigurieren, um den Trigger problemlos laufen zu lassen?

    Vielen Dank im Voraus!!!

  • #2
    Hallo,

    was machst Du innerhalb des Triggers? Es sieht so aus, dass Du aus dem Trigger heraus versuchst auf externe Ressourcen zuzugreifen (Dateisystem, Webservice o.ä.), ist das so? Die Fehlermeldung
    The protected resources (only available with full trust) were: All
    The demanded resources were: UI
    deutet zumindest darauf hin. Lass doch mal 'n büsch'n Code sehen....

    Bis dann
    Olaf

    Comment


    • #3
      Hallo,

      vielen Dank für Deine Antwort.

      Ich möchte gern nach einem INSERT in einer Datenbank eine andere Application starten lassen. Ich konnte eben das Problem lösen, allerdings bin ich natürlich gleich auf das nächste gestoßen...

      Der Trigger hat jetzt die entsprechenden Berechtigungen, sodass externe Ressourcen geladen werden können. DAs hatte ich beim letzten Post nicht beachtet.

      Nun möchte ich einfach nach einem Insert eine Messagebox (als Test) anzeigen lassen. Dabei kommt folgende Fehlermeldung

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      Meldung 6522, Ebene 16, Status 1, Prozedur Audit_ADDRESS, Zeile 1
      .NET Framework-Fehler beim Ausführen der benutzerdefinierten Routine oder des benutzerdefinierten Aggregats "Audit_ADDRESS":
      System.IO.FileNotFoundException: Die Datei oder Assembly System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
      System.IO.FileNotFoundException:
      at Microsoft.VisualBasic.Interaction.MsgBox(Object Prompt, MsgBoxStyle Buttons, Object Title)
      at AuditCommon.Triggers.AuditCommon()
      .
      Die Anweisung wurde beendet.

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      hier ist mal ein bissl code: (er springt also in den Trigger und bei Msgbox kommt der Fehler?!)

      Partial Public Class Triggers
      <Microsoft.SqlServer.Server.SqlTrigger(Name:="Audi tCommon", Event:="FOR UPDATE, INSERT, DELETE")> _
      Public Shared Sub AuditCommon()

      Try

      #If DEBUG Then
      EmitDebugMessage("Enter Trigger")
      Microsoft.VisualBasic.MsgBox("enter trigger...", MsgBoxStyle.Information)
      #End If

      ' Grab the already-open Connection to use as an argument
      #If DEBUG Then
      EmitDebugMessage("Open Connection")
      MsgBox("open connection...", MsgBoxStyle.Information)
      #End If
      Dim Context As SqlTriggerContext = SqlContext.TriggerContext()
      Dim Connection As New SqlConnection("context connection=true")
      Connection.Open()

      ' Load the "inserted" table
      #If DEBUG Then
      EmitDebugMessage("Load INSERTED")
      MsgBox("load Table inserted...", MsgBoxStyle.Information)
      #End If

      Dim TableLoader As New SqlDataAdapter("select * from inserted", Connection)
      Dim InsertedTable As New Data.DataTable
      TableLoader.Fill(InsertedTable)

      ' Load the "deleted" table
      #If DEBUG Then
      EmitDebugMessage("Load DELETED")
      Microsoft.VisualBasic.MsgBox("load Table delete...", MsgBoxStyle.Information)
      #End If
      TableLoader.SelectCommand.CommandText = "select * from deleted"
      Dim DeletedTable As New Data.DataTable
      TableLoader.Fill(DeletedTable)

      ' Prepare the "audit" table for insertion
      #If DEBUG Then
      EmitDebugMessage("Load AUDIT schema for insertion")
      #End If
      Dim AuditAdapter As New SqlDataAdapter("select * from audit where 1 = 0", Connection)
      Dim AuditTable As New Data.DataTable
      AuditAdapter.FillSchema(AuditTable, SchemaType.Source)
      Dim AuditCommandBuilder As SqlCommandBuilder = New SqlCommandBuilder(AuditAdapter)

      ' Create DataRow objects corresponding to the trigger table rows.
      #If DEBUG Then
      EmitDebugMessage("Create internal representations of trigger table rows")
      #End If
      Dim TableName As String = ""

      Dim InsertedRow As Data.DataRow = Nothing
      If InsertedTable.Rows.Count > 0 Then
      InsertedRow = InsertedTable.Rows(0)
      TableName = DeriveTableNameFromKeyFieldName(InsertedTable.Colu mns(0).ColumnName)
      End If

      Dim DeletedRow As Data.DataRow = Nothing
      If DeletedTable.Rows.Count > 0 Then
      DeletedRow = DeletedTable.Rows(0)
      TableName = DeriveTableNameFromKeyFieldName(DeletedTable.Colum ns(0).ColumnName)
      End If

      ' get the current database user
      Dim CurrentUserCmd As New SqlCommand("select current_user", Connection)
      Dim CurrentUser As String = CurrentUserCmd.ExecuteScalar().ToString()

      ' Perform different audits based on the type of action.
      Select Case Context.TriggerAction

      Case TriggerAction.Insert

      ' If the INSERTED row is not populated, then this is not a valid insertion.
      If InsertedRow IsNot Nothing Then

      ' DEBUG output indicating row insertion
      #If DEBUG Then
      EmitDebugMessage("Create INSERT Audit: Row = '" & InsertedRow.Item(0).ToString & "'")
      #End If

      ' Create audit record indicating field change
      Dim AuditRow As Data.DataRow
      AuditRow = AuditTable.NewRow()

      ' populate fields common to all audit records
      Dim RowId As Int64 = CType(InsertedRow.Item(0), Int64)
      ' use "Inserted.TableName" when Microsoft fixes the CLR to supply it
      WriteCommonAuditData(AuditRow, TableName, RowId, CurrentUser, "INSERT")

      ' insert the new row into the audit table
      AuditTable.Rows.InsertAt(AuditRow, 0)

      End If

      End Select

      ' update the audit table
      AuditAdapter.Update(AuditTable)

      ' finish
      #If DEBUG Then
      EmitDebugMessage("Exit Trigger")
      #End If

      Catch e As Exception

      ' Put exception handling code here if you want to connect this to your
      ' database-based error logging system. Without this Try/Catch block,
      ' any error in the trigger routine will stop the event that fired the trigger.
      ' This is early-stage development and we're not expecting any exceptions,
      ' so for the moment we just need to know about them if they occur.
      Throw

      End Try

      End Sub
      ' Write data into the fields of an Audit table row that is common to all
      ' types of audit activities.
      Private Shared Sub WriteCommonAuditData(ByVal AuditRow As DataRow, ByVal TableName As String, ByVal RowId As Int64, ByVal CurrentUser As String, ByVal Operation As String)
      With AuditRow
      ' write common audit fields
      .Item("TableName") = TableName
      .Item("RowId") = RowId
      .Item("OccurredAt") = Now()
      .Item("PerformedBy") = CurrentUser
      .Item("Operation") = Operation
      End With
      End Sub
      ' SQL CLR does not deliver the proper table name from either InsertedTable.TableName
      ' or DeletedTable.TableName, so we must use a substitute based on our key naming
      ' convention. We assume that in each table, the KeyFieldName = TableName + "Id".
      ' Remove this routine and its uses as soon as we can get the table name from the CLR.
      Private Shared Function DeriveTableNameFromKeyFieldName(ByVal KeyFieldName As String) As String
      Return Left(KeyFieldName, Len(KeyFieldName) - 2).ToUpper() ' assumes KeyName = TableName & "Id"
      End Function
      ' Emit debug messages. This function gives us the option to turn off debugging
      ' messages by changing one value (here).
      #If DEBUG Then
      Private Shared Sub EmitDebugMessage(ByVal Message As String)
      SqlContext.Pipe.Send(Message)
      End Sub
      #End If
      End Class



      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


      Wie kann ich diese Verweise nachkonfigurieren, denn ein Hinzufügen von bsp.
      System.Windows.Forms ist hier nicht möglich.

      Ist es denn überhaupt möglich Windows Form Elemente aus einem Trigger aufzurufen???

      Vielen Dank schon mal für die Zuarbeit!

      MiCHA

      Comment


      • #4
        Hallo,

        Ist es denn überhaupt möglich Windows Form Elemente aus einem Trigger aufzurufen???
        Nein - denn die MessageBox ist für den interaktiv angemeldeten Benutzer unsichtbar, so dass niemand den OK-Button anklicken kann und der Trigger somit bis zum Herunterfahren des MS SQL Server-Dienstes hängen bleibt.

        Wenn eine andere Anwendung aus dem Trigger heraus informiert werden soll, während die Notification Services des MS SQL Server 2005 eine mögliche Implementierungsalternative.

        Comment


        • #5
          Hallo Herr Kosch,

          vielen Dank für Ihre Hilfe.
          Es ist eigentlich auch nicht sinnvoll eine MsgBox anzeigen zu lassen.
          Ich hatte nur zu TEstzwecken diese anzeigen wollen und bin da wohl drüber gestolpert.

          Wie kann ich den Notificationservice darin einbinden bzw. damit arbeiten?

          Vielen Dank nochmals...

          Micha

          Comment

          Working...
          X