Track column changes - single SQL CLR Trigger for multiple Targets/Tables
SQL CLR Trigger:
Is there a开发者_C百科 way to get Target / Table name from CLR code?
Purpose:
I'm building a universal SQL CLR Trigger to track column changes in multiple Tables.
Info:
The same CLR trigger can be bound to multiple Tables.
As long as CLR Trigger is bound to a Table, it fires just fine on any Table no matter what Target/Table was specified in CLR Trigger Attribute. It means I can create 1 CLR Trigger and use it for all Tables that require change tracking.
The problem is in calling table name / trigger name identification within the Trigger. I tried all DMV objects, so far nothing that solves the problem. Btw, @@PROCID is not accessible in CLR.
PS: I have a solution, but is can not be considered as nice and reliable.
The tip is to have the Trigger Target set to the right level. Although it's not CLR specific the details can be found in MSDN here but the following would probably work for you.
[Microsoft.SqlServer.Server.SqlTrigger (Name="TriggerName", Target="database", Event="FOR UPDATE")]
Then to figure out what table or field changed access the EventData which is in a SqlXml variable. I created a class similar to the following to access the properties in a structured way.
using System.Data.SqlTypes;
using System.Xml;
using System.Xml.Serialization;
namespace CLRSQLTrigger
{
public class SqlEventData
{
readonly XmlDocument document = new XmlDocument();
public SqlEventData(SqlXml sqlXml)
{
if (sqlXml != SqlXml.Null)
{
document.LoadXml(sqlXml.Value);
}
}
public string EventType
{
get { return document.GetElementsByTagName("EventType")[0].InnerText; }
}
}
}
The values received by a given action are alot easier to decode by dumping the SqlXml variable that is returned when your event is fired. Once you have those values you can use a syntax similar to the EventType Property above or use the GetElementsByTagName method in your code directly. There are literally 100+ events and each event has 4-12 fields, so that part is up to you. If you are serious there is an XSD of the different combinations but it might slow you down compared to the debug method. The XSD path is going to be something like
C:\Program Files\Microsoft SQL Server\100\Tools\Binn\schemas\sqlserver\2006\11\events
public partial class Triggers
{
[SqlTrigger(Name = "TriggerName", Target = "TableName", Event = "FOR UPDATE")]
public static void TriggerName ()
{
SqlTriggerContext triggerContext = SqlContext.TriggerContext;
if (triggerContext.TriggerAction == TriggerAction.Update)
{
SqlConnection connection = new SqlConnection("Context Connection=true");
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "SELECT * FROM INSERTED,DELETED";
connection.Open();
SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
if (SqlContext.TriggerContext.IsUpdatedColumn(reader.GetOrdinal("State")))
{
reader.Read();
long MessageID = Convert.ToInt64(reader["MessageID"]);
int State = Convert.ToInt32(reader["State"]);
reader.Close();
if (State == 1)
FunctionName.SendMassage(MessageID);
}
}
}
}
精彩评论