PDA

Vollständige Version anzeigen : Trigger


FrankMueller
23.01.2008, 06:46
Gibt es irgendwo eine gute Online Hilfe bezüglich Trigger unter .NET?
Oder kann mir einer erklären,wie ich einen Trigger in VIsual Studio schreibe und ihn dann auf der Datenbank aufrufe????Welche Arten es gibt etc...ich bin nirgends fündig geworden!

hcscherzer
23.01.2008, 07:18
Moin Frank,
Trigger sind im Prinzip stored procedures, die bei bestimmten Ereignissen (UPDATE, INSERT DELETE) auf Datenbank-Tabellen automatisch ausgeführt werden.
Das sind spezifische SQL Vorgänge die in dem Datenbanksystem ablaufen.
Du kannst den Trigger also in .NET nicht 'schreiben' sondern nur eine entsprechende SQL Anweisung an die DB schicken, die einen Trigger erstellt oder deaktiviert etc.

Noodles
23.01.2008, 09:25
Moin Frank,
Du kannst den Trigger also in .NET nicht 'schreiben'

Das ist leider falsch!

http://msdn2.microsoft.com/en-us/library/938d9dz2.aspx

hcscherzer
23.01.2008, 10:13
Das ist leider falsch!Schade eigentlich. Na ja, wieder was dazugelernt. :)
Kurze Nachfrage: wo ist der Unterschied (oder was ist vorteilhafter), ob ich das mit der Trigger-Klasse in .NET mache oder ob ich per .ExecuteNonQuery einen SQL Befehl absetze a la Create Trigger ...

Noodles
24.01.2008, 06:59
Das keine Frage speziell wegen der Trigger. Man kann auch Funktionen oder Prozeduren mit .NET schreiben. Musst Du mal googlen, da findet man einiges.

http://blogs.ittoolbox.com/visualbasic/dotnet/archives/clr-stored-procs-versus-tsql-stored-procs-round-1-10415

FrankMueller
24.01.2008, 14:05
So,habe nun einen Trigger von der msdn2.microsoft Seite übernommen,aber es kommt folgende Fehlermeldung:
Meldung 6522, Ebene 16, Status 1, Prozedur TriggerTest, Zeile 1
.NET Framework-Fehler beim Ausführen der benutzerdefinierten Routine oder des benutzerdefinierten Aggregats 'TriggerTest':
System.InvalidOperationException: Invalid attempt to read when no data is present.
System.InvalidOperationException:
at System.Data.SqlClient.SqlDataReaderSmi.EnsureOnRow(String operationName)
at System.Data.SqlClient.SqlDataReaderSmi.GetValue(Int32 ordinal)
at Test.CLRTriggers.DropTableTrigger()
Wenn ich einen Datareader read() mache,dann kommt diese Fehlermeldung nicht,aber es kommt,dass bereits ein Datareader geöffnet ist und der erst geschlossen werden muss!Leider kann ich bei context connection=true nicht dahinter setzen "MARS"=true

Hier mein Code:Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient
Imports System.Text.RegularExpressions
Imports System.IO
'The Partial modifier is only required on one class definition per project.
Partial Public Class CLRTriggers
<Microsoft.SqlServer.Server.SqlTrigger(Name:="TriggerTest", Target:="Users", Event:="FOR INSERT")> _
Public Shared Sub DropTableTrigger()
Dim triggContext As SqlTriggerContext
Dim connection As New SqlConnection("context connection=True")
Dim command As SqlCommand
Dim objReader As SqlDataReader
Dim username As String
Dim real As String

triggContext = SqlContext.TriggerContext
connection.Open()
command = connection.CreateCommand()

Select Case triggContext.TriggerAction
Case TriggerAction.Insert
command.CommandText = "SELECT * FROM inserted"

objReader = command.ExecuteReader()

username = CType(objReader(0), String)
real = CType(objReader(1), String)
command.CommandText = "INSERT dbo.UserNameAudit " & _
"VALUES ('" & username & "','" & real & "')"
SqlContext.Pipe.Send(command.CommandText)
SqlContext.Pipe.ExecuteAndSend(command)
SqlContext.Pipe.Send("You inserted:" & username)

End Select

End Sub

Public Shared Function IsValidEMailAddress(ByVal emailAddress As String) As Boolean

Return Regex.IsMatch(emailAddress, "^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$")

End Function
End Class

hcscherzer
24.01.2008, 15:15
Man kann auch Funktionen oder Prozeduren mit .NET schreibenAha. Meine Frage war aber: Was ist der Vorteil (bzw. der Unterschied) gegenüber der Programmierung in SQL?

FrankMueller
24.01.2008, 18:26
Also einen Vorteil sehe ich darin,das man alles debuggen kann.Aber hat keiner ne Lösung für mein Problem?Warum das so nicht klappt...Es ist ja sogar ein Beispiel,was eigentlich funktionieren sollte...

Noodles
25.01.2008, 06:27
Google mal ob MARS in CLR Triggern überhaupt möglich ist.
Debuggen kann ich auch SQL per Visual Studio.

Man kann aber Dinge machen, für die SQL nicht die optimale Sprache ist, sei es Performance oder Sicherheit.

FrankMueller
25.01.2008, 09:06
Kann ich denn in den CLR Triggern globale Variablen definieren?Und in einer Paketkonfiguration die dann ändern???
Und noch eins,kann ich in dem Programmcode eines CLR-Triggers außerhalb definierte Funktionen oder Stored Procedures aufrufen,also wenn er in den Trigger springt soll er meine Stored Procedure aufrufen,wenn ja,mit welchem Befehl ist das auf .net Seite möglich???

FrankMueller
28.01.2008, 09:27
Hat niemand eine Idee?Habe jetzt einen Trigger geschrieben und muss dort zwei Verbindungen öffnen,aber wie mache ich das??Also eine im Trigger selbst,um einen Select abzusetzen und weiter unten in der Funktion ebenfalls!Wenn ich alles in den Trigger packe kann ich mit der context connection arbeiten,ist mir aber zu unübersichtlich,daher würd ich gerne die funktion auslagern!So wie ich es geplant hatte funktioniert es nicht...

Imports System

Imports System.Data

Imports System.Data.Sql

Imports System.Data.SqlTypes

Imports Microsoft.SqlServer.Server

Imports System.Data.SqlClient

Imports System.Text.RegularExpressions

Imports System.IO



'The Partial modifier is only required on one class definition per project.

Partial Public Class Triggers

<Microsoft.SqlServer.Server.SqlTrigger(Name:="AggregateKnz", Target:="TESTDaten", Event:="FOR INSERT")> _

Public Shared Sub AggregateKnz()

Dim triggContext As SqlTriggerContext

Dim connection As New SqlConnection("context connection=true")

Dim command As SqlCommand

Dim reader As SqlDataReader

Dim iKennzahl As Integer

Dim iPeriode As Integer

Dim iZeitdim As Integer

Dim bFound As Boolean

Dim iAnzahl As Integer



triggContext = SqlContext.TriggerContext

connection.Open()

command = connection.CreateCommand()

Select Case triggContext.TriggerAction

Case TriggerAction.Insert

command.CommandText = "SELECT ID, Periode, ZeitDim_ID FROM " + "inserted"

reader = command.ExecuteReader()

reader.Read()

iKennzahl = CInt(reader("ID"))

iPeriode = CInt(reader("Periode"))

iZeitdim = CInt(reader("ZeitDim_ID"))

reader.Close()

If IsValidBasis(iKennzahl) Then

If bFound = True Then

command.CommandText = "INSERT dbo.UserNameAudit " & _

"VALUES (" & iKennzahl & ", " & iPeriode & ")"

SqlContext.Pipe.Send(command.CommandText)

SqlContext.Pipe.ExecuteAndSend(command)

End If

End If



End Select

End Sub

Public Shared Function IsValidBasis(ByVal Kennzahl As Integer) As Boolean

Dim cmd As New SqlCommand

Dim iAnzahl As Integer

Dim sConnStr As String

sConnStr = ("server = SQLSERVER; UID= Testperson; PWD=test; database=Test;")

Dim connSQL1 As New SqlConnection(sConnStr)

connSQL1.Open()

cmd.CommandText = "SELECT * FROM dbo.berechnet_sich where šber_ID =" & Kennzahl

SqlContext.Pipe.Send(cmd.CommandText)

iAnzahl = CType(cmd.ExecuteScalar, Integer)

If iAnzahl = 0 Then

Return True

Else : Return False

End If

connSQL1.Close()

End Function

End Class