### Start Method Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Explains how to start the table monitoring process and subscribe to change events. It also covers how to specify custom timeouts for the WAITFOR command and the watchdog mechanism. ```APIDOC ## Start Method ### Description Begins monitoring the table for changes. The Start method initializes the SQL Server infrastructure (triggers, queues, service broker) and starts listening for notifications. It accepts timeout parameters for the WAITFOR command and the watchdog cleanup mechanism. ### Method `Start(int timeOut = 120, int watchDogTimeOut = 180)` ### Endpoint N/A (This is a method of the `SqlTableDependency` class) ### Parameters - **timeOut** (int) - Optional - The timeout in seconds for the WAITFOR command. Minimum value is 60. - **watchDogTimeOut** (int) - Optional - The timeout in seconds for the watchdog cleanup mechanism. Minimum value is `timeOut + 60`. ### Request Example ```csharp using TableDependency.SqlClient; using System; public class Product { public int Id { get; set; } public string Name { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var tableDependency = new SqlTableDependency(connectionString)) { // Subscribe to change event (required before calling Start) tableDependency.OnChanged += (sender, e) => { Console.WriteLine($"Operation: {e.ChangeType}"); Console.WriteLine($"Entity: {e.Entity.Name}"); }; // Start with default timeouts (120s WAITFOR, 180s watchdog) tableDependency.Start(); // Or specify custom timeouts // timeOut: WAITFOR timeout in seconds (min 60) // watchDogTimeOut: Cleanup timeout when no listeners (min timeOut + 60) // tableDependency.Start(timeOut: 120, watchDogTimeOut: 300); Console.WriteLine("Listening for changes... Press any key to stop."); Console.ReadKey(); // Stop monitoring and cleanup database objects tableDependency.Stop(); } ``` ### Response N/A (This method initiates monitoring and does not return a value directly.) ### Error Handling Refer to the `OnError` event for error notifications. ``` -------------------------------- ### Initialize and Start SqlTableDependency Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Instantiate the dependency with a model and connection string, then subscribe to the OnChanged event and start monitoring. ```csharp using (var tableDependency = new SqlTableDependency(ConnectionString, TableName, mapper, null, false, namingToUse)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); .... } ``` -------------------------------- ### Install SqlTableDependency NuGet Package Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Install the SqlTableDependency NuGet package to add the component to your C# project. ```bash Install-Package SqlTableDependency ``` -------------------------------- ### Start SqlTableDependency Monitoring Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Starts the SqlTableDependency monitoring process. This method initializes necessary SQL Server objects and begins listening for table changes. It can be called with default or custom timeouts for the WAITFOR command and watchdog mechanism. ```csharp using TableDependency.SqlClient; using System; public class Product { public int Id { get; set; } public string Name { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var tableDependency = new SqlTableDependency(connectionString)) { // Subscribe to change event (required before calling Start) tableDependency.OnChanged += (sender, e) => { Console.WriteLine($"Operation: {e.ChangeType}"); Console.WriteLine($"Entity: {e.Entity.Name}"); }; // Start with default timeouts (120s WAITFOR, 180s watchdog) tableDependency.Start(); // Or specify custom timeouts // timeOut: WAITFOR timeout in seconds (min 60) // watchDogTimeOut: Cleanup timeout when no listeners (min timeOut + 60) // tableDependency.Start(timeOut: 120, watchDogTimeOut: 300); Console.WriteLine("Listening for changes... Press any key to stop."); Console.ReadKey(); // Stop monitoring and cleanup database objects tableDependency.Stop(); } ``` -------------------------------- ### Configure Logging and Event Handling for SqlTableDependency (C#) Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Set up SqlTableDependency with verbose logging and custom trace listeners. This example demonstrates subscribing to OnChanged, OnError, and OnStatusChanged events, and configuring trace output to the console or a file. ```C# using (var tableDependency = new SqlTableDependency(connectionString, "Customer")) { tableDependency.OnStatusChanged += TableDependency_OnStatusChanged; tableDependency.OnChanged += TableDependency_Changed; tableDependency.OnError += TableDependency_OnError; tableDependency.TraceLevel = TraceLevel.Verbose; tableDependency.TraceListener = new TextWriterTraceListener(Console.Out); // OR tableDependency.TraceListener = new TextWriterTraceListener(File.Create("c:\\temp\\output.txt")); tableDependency.Start(); Console.WriteLine(@"Waiting for receiving notifications..."); Console.WriteLine(@"Press a key to stop"); Console.ReadKey(); tableDependency.Stop(); } ``` -------------------------------- ### Initialize SqlTableDependency with Model in C# Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Create a SqlTableDependency instance using a model class that has DataAnnotations. The table name and mapper are inferred from the model attributes. Start listening for changes. ```csharp SqlTableDependency tableDependency = new SqlTableDependency(ConnectionString); tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); ``` -------------------------------- ### Monitor Database Changes in .NET Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Starts the monitoring process and handles reconnection logic for the SqlTableDependency instance. ```csharp Console.WriteLine($"Consider reconnecting: {ex.Message}"); }; monitor.StartMonitoring(); Console.WriteLine("Stock price monitor is running. Press Enter to stop..."); Console.ReadLine(); } } } ``` -------------------------------- ### Configure and Start SqlTableDependency with Custom Mapping Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Custom-map-between-model-property-and-table-column-using-ModelToTableMapper-T This C# code demonstrates how to set up SqlTableDependency with a ModelToTableMapper to bridge the gap between the C# model and the database table columns. Ensure the connectionString is properly defined. ```csharp var mapper = new ModelToTableMapper(); mapper.AddMapping(c => c.Name, "First Name"); mapper.AddMapping(c => c.Surname, "Last Name"); var tableDependency = new SqlTableDependency( connectionString, mapper: mapper); tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); ``` -------------------------------- ### Monitor Table Changes with Old Values Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Include-old-values Set includeOldValues to true to retrieve the old value in the OnChanged event handler. This example sets up a dependency on the 'Clients' table. ```C# string ConnectionString = "data source=.;initial catalog=myDB;integrated security=True"; string tableName = "Clients"; string schemaName = "dbo"; using(var tableDependency = new SqlTableDependency( ConnectionString, schemaName: schemaName, tableName: tableName, includeOldValues: true)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); Console.WriteLine("Waiting for receiving notifications..."); Console.WriteLine("Press a key to stop"); Console.ReadKey(); } } ``` -------------------------------- ### Monitor SqlTableDependency Status with OnStatusChanged Event Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Use the OnStatusChanged event to monitor the lifecycle of the SqlTableDependency listener, including starting, running, and error states. This helps in managing the health of the notification service. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Base.EventArgs; using System; public class Order { public int Id { get; set; } public decimal Total { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var tableDependency = new SqlTableDependency(connectionString)) { tableDependency.OnChanged += (s, e) => Console.WriteLine($"Order changed: {e.ChangeType}"); tableDependency.OnStatusChanged += (sender, e) => { switch (e.Status) { case TableDependencyStatus.Starting: Console.WriteLine("SqlTableDependency is starting..."); break; case TableDependencyStatus.Started: Console.WriteLine("SqlTableDependency started successfully."); break; case TableDependencyStatus.WaitingForNotification: Console.WriteLine("Waiting for table changes..."); break; case TableDependencyStatus.StopDueToCancellation: Console.WriteLine("Stopped due to user cancellation."); break; case TableDependencyStatus.StopDueToError: Console.WriteLine("Stopped due to an error."); break; } }; tableDependency.Start(); // Access current status programmatically Console.WriteLine($"Current Status: {tableDependency.Status}"); Console.ReadKey(); } ``` -------------------------------- ### Implement Real-Time Stock Price Monitoring Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt A robust implementation of a monitoring class that maps database columns, configures change tracking, and handles lifecycle events. Ensure the connection string is valid and the database user has appropriate permissions for DML triggers. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Base.EventArgs; using TableDependency.SqlClient.Where; using System; using System.Linq.Expressions; using System.Threading; public class StockPrice { public int Id { get; set; } public string Symbol { get; set; } public decimal Price { get; set; } public decimal Change { get; set; } public DateTime LastUpdated { get; set; } } public class StockPriceMonitor : IDisposable { private SqlTableDependency _dependency; private readonly string _connectionString; private bool _isRunning; public event Action StockChanged; public event Action StatusChanged; public event Action ErrorOccurred; public StockPriceMonitor(string connectionString) { _connectionString = connectionString; } public void StartMonitoring(string[] symbolsToWatch = null) { // Map model to table columns var mapper = new ModelToTableMapper(); mapper.AddMapping(s => s.Symbol, "stock_symbol"); mapper.AddMapping(s => s.Price, "current_price"); mapper.AddMapping(s => s.Change, "price_change"); mapper.AddMapping(s => s.LastUpdated, "last_update"); // Only monitor price changes var updateOf = new UpdateOfModel(); updateOf.Add(s => s.Price, s => s.Change); // Create dependency with configuration _dependency = new SqlTableDependency( _connectionString, tableName: "stock_prices", schemaName: "trading", mapper: mapper, updateOf: updateOf, notifyOn: DmlTriggerType.All, includeOldValues: true); // Wire up events _dependency.OnChanged += OnStockChanged; _dependency.OnStatusChanged += OnStatusChanged; _dependency.OnError += OnError; // Start with extended timeouts for debugging _dependency.Start(timeOut: 120, watchDogTimeOut: 300); _isRunning = true; } private void OnStockChanged(object sender, RecordChangedEventArgs e) { var stock = e.Entity; // Log the change Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {e.ChangeType}: {stock.Symbol}"); Console.WriteLine($" Price: ${stock.Price:N2} (Change: {stock.Change:+0.00;-0.00})"); if (e.ChangeType == ChangeType.Update && e.EntityOldValues != null) { var oldPrice = e.EntityOldValues.Price; var priceDiff = stock.Price - oldPrice; var percentChange = oldPrice != 0 ? (priceDiff / oldPrice) * 100 : 0; Console.WriteLine($" Previous: ${oldPrice:N2} ({percentChange:+0.00;-0.00}%)"); } // Notify subscribers StockChanged?.Invoke(stock, e.ChangeType); } private void OnStatusChanged(object sender, StatusChangedEventArgs e) { var message = e.Status switch { TableDependencyStatus.Starting => "Initializing stock monitor...", TableDependencyStatus.Started => "Stock monitor started", TableDependencyStatus.WaitingForNotification => "Monitoring stock prices...", TableDependencyStatus.StopDueToCancellation => "Monitor stopped by user", TableDependencyStatus.StopDueToError => "Monitor stopped due to error", _ => $"Status: {e.Status}" }; Console.WriteLine($"[STATUS] {message}"); StatusChanged?.Invoke(message); } private void OnError(object sender, ErrorEventArgs e) { Console.WriteLine($"[ERROR] {e.Error.Message}"); ErrorOccurred?.Invoke(e.Error); } public void StopMonitoring() { if (_isRunning) { _dependency?.Stop(); _isRunning = false; } } public void Dispose() { StopMonitoring(); _dependency?.Dispose(); } } // Usage class Program { static void Main() { var connectionString = "data source=.;initial catalog=TradingDB;integrated security=True"; using (var monitor = new StockPriceMonitor(connectionString)) { monitor.StockChanged += (stock, changeType) => { if (changeType == ChangeType.Update && Math.Abs(stock.Change) > 5) { Console.WriteLine($"*** ALERT: Significant price movement for {stock.Symbol}! ***"); } }; monitor.ErrorOccurred += ex => { // Implement reconnection logic here ``` -------------------------------- ### SqlTableDependency Constructor Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Demonstrates how to create a SqlTableDependency instance to monitor a specific database table. It shows basic usage and advanced configuration with table name, schema, column mapping, update filters, WHERE clauses, and DML trigger types. ```APIDOC ## SqlTableDependency Constructor ### Description Creates a new instance of SqlTableDependency to monitor a specific database table. The constructor accepts a connection string and various optional parameters for customizing monitoring behavior including table name, schema, column mapping, update filters, WHERE conditions, and DML trigger types. ### Method `SqlTableDependency` ### Endpoint N/A (This is a class constructor) ### Parameters #### Constructor Overloads **Basic Constructor:** - `connectionString` (string) - Required - The database connection string. **Full Constructor:** - `connectionString` (string) - Required - The database connection string. - `tableName` (string) - Optional - The name of the table to monitor. If not provided, it's inferred from the model class name. - `schemaName` (string) - Optional - The schema name of the table. Defaults to 'dbo'. - `mapper` (ModelToTableMapper) - Optional - An object for mapping model properties to table columns. - `updateOf` (UpdateOfModel) - Optional - Specifies which columns to monitor for update operations. - `filter` (SqlTableDependencyFilter) - Optional - A filter to apply a WHERE clause to the monitored changes. - `notifyOn` (DmlTriggerType) - Optional - Specifies the DML operations (INSERT, UPDATE, DELETE) to receive notifications for. Defaults to all. - `executeUserPermissionCheck` (bool) - Optional - Whether to check user permissions on startup. Defaults to false. - `includeOldValues` (bool) - Optional - Whether to include old values in update notifications. Defaults to false. ### Request Example ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Where; using System; using System.Linq.Expressions; // Define model matching your database table public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public int Quantity { get; set; } } // Basic constructor - model name matches table name var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var dep = new SqlTableDependency(connectionString)) { // Table name inferred from class name "Product" } // Full constructor with all options var mapper = new ModelToTableMapper(); mapper.AddMapping(c => c.Name, "ProductName"); // Map property to different column name var updateOf = new UpdateOfModel(); updateOf.Add(p => p.Price); // Only notify when Price column changes Expression> filterExpression = p => p.Quantity > 0; var filter = new SqlTableDependencyFilter(filterExpression); using (var dep = new SqlTableDependency( connectionString, tableName: "Products", // Explicit table name schemaName: "inventory", // Schema name (default: dbo) mapper: mapper, // Column-to-property mapping updateOf: updateOf, // Monitor specific columns for updates filter: filter, // WHERE clause filter notifyOn: DmlTriggerType.Insert | DmlTriggerType.Update, // DML operations to monitor executeUserPermissionCheck: true, // Check user permissions on start includeOldValues: true)) // Include old values in update notifications { dep.OnChanged += (sender, e) => Console.WriteLine($"Change detected: {e.ChangeType}"); dep.Start(); } ``` ### Response N/A (This is a constructor, it does not return a value directly but initializes an object.) ### Error Handling Refer to the `OnError` event for error notifications. ``` -------------------------------- ### Create SQL Table Schema Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Model-and-properties-with-same-name-of-table-and-columns Defines the schema for the 'Customers' table in SQL Server. ```SQL CREATE TABLE [Customers]( [Id] [int] IDENTITY(1, 1) NOT NULL, [Name] [nvarchar](50) NULL, [Surname] [nvarchar](50) NULL) ``` -------------------------------- ### Define SQL Schema and Table Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Code-First-Data-Annotations-to-map-model-with-database-table Create a custom schema and table structure in SQL Server. ```SQL CREATE SCHEMA [Transaction] GO CREATE TABLE [Transaction].[Items] ( TransactionItemId uniqueidentifier NULL, Description nvarchar(50) NOT NULL) GO ``` -------------------------------- ### Set up SqlTableDependency for Notifications Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Model-and-properties-with-same-name-of-table-and-columns Initializes SqlTableDependency to listen for changes on the 'Customers' table. Ensure the connection string is correct and the OnChanged event handler is defined. ```C# string conString = "data source=.;initial catalog=myDB;integrated security=True"; using(var tableDependency = new SqlTableDependency(conString)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); Console.WriteLine("Waiting for receiving notifications..."); Console.WriteLine("Press a key to stop"); Console.ReadKey(); } ``` -------------------------------- ### Implement SqlTableDependency Monitoring Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/blob/master/README.md Initialize the dependency with a connection string and optional mapper, then subscribe to the Changed event to process notifications. ```C# public class Program { private static string _con = "data source=.; initial catalog=MyDB; integrated security=True"; public static void Main() { // The mapper object is used to map model properties // that do not have a corresponding table column name. // In case all properties of your model have same name // of table columns, you can avoid to use the mapper. var mapper = new ModelToTableMapper(); mapper.AddMapping(c => c.Surname, "Second Name"); mapper.AddMapping(c => c.Name, "First Name"); // Here - as second parameter - we pass table name: // this is necessary only if the model name is different from table name // (in our case we have Customer vs Customers). // If needed, you can also specifiy schema name. using (var dep = new SqlTableDependency(_con, "Customers", mapper: mapper)); { dep.OnChanged += Changed; dep.Start(); Console.WriteLine("Press a key to exit"); Console.ReadKey(); dep.Stop(); } } public static void Changed(object sender, RecordChangedEventArgs e) { var changedEntity = e.Entity; Console.WriteLine("DML operation: " + e.ChangeType); Console.WriteLine("ID: " + changedEntity.Id); Console.WriteLine("Name: " + changedEntity.Name); Console.WriteLine("Surname: " + changedEntity.Surname); } ``` -------------------------------- ### Configure SQL Server for SqlTableDependency Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Enables Service Broker and grants the necessary permissions for the database user to monitor tables. ```sql -- Enable Service Broker (required) ALTER DATABASE MyDatabase SET ENABLE_BROKER; -- Optional: Set TRUSTWORTHY if using custom QueueExecuteAs ALTER DATABASE MyDatabase SET TRUSTWORTHY ON; -- Grant required permissions if not using db_owner role GRANT ALTER ON SCHEMA::dbo TO [YourUser]; GRANT CONNECT TO [YourUser]; GRANT CONTROL ON SCHEMA::dbo TO [YourUser]; GRANT CREATE CONTRACT TO [YourUser]; GRANT CREATE MESSAGE TYPE TO [YourUser]; GRANT CREATE PROCEDURE TO [YourUser]; GRANT CREATE QUEUE TO [YourUser]; GRANT CREATE SERVICE TO [YourUser]; GRANT EXECUTE TO [YourUser]; GRANT SELECT TO [YourUser]; GRANT SUBSCRIBE QUERY NOTIFICATIONS TO [YourUser]; GRANT VIEW DATABASE STATE TO [YourUser]; GRANT VIEW DEFINITION TO [YourUser]; -- Check if Service Broker is enabled SELECT name, is_broker_enabled FROM sys.databases WHERE name = 'MyDatabase'; -- Check database compatibility level (should be 2008 R2 or later: version >= 661) DECLARE @DBINFO TABLE ([ParentObject] VARCHAR(60),[Object] VARCHAR(60),[Field] VARCHAR(30),[VALUE] VARCHAR(4000)) INSERT INTO @DBINFO EXECUTE sp_executesql N'DBCC DBINFO WITH TABLERESULTS' SELECT [Field], [VALUE] FROM @DBINFO WHERE [Field] IN ('dbi_createversion','dbi_version'); ``` -------------------------------- ### Define C# Model for Table Mapping Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/blob/master/README.md Create a class representing the table columns to be monitored. Only include properties for the columns you wish to track. ```C# public class Customer { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } } ``` -------------------------------- ### SqlTableDependency Full Constructor with Options Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Demonstrates the full constructor for SqlTableDependency, allowing customization of table name, schema, column mapping, update filters, WHERE clause, and DML trigger types. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Where; using System; using System.Linq.Expressions; // Define model matching your database table public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public int Quantity { get; set; } } // Full constructor with all options var mapper = new ModelToTableMapper(); mapper.AddMapping(c => c.Name, "ProductName"); // Map property to different column name var updateOf = new UpdateOfModel(); updateOf.Add(p => p.Price); // Only notify when Price column changes Expression> filterExpression = p => p.Quantity > 0; var filter = new SqlTableDependencyFilter(filterExpression); using (var dep = new SqlTableDependency( connectionString, tableName: "Products", // Explicit table name schemaName: "inventory", // Schema name (default: dbo) mapper: mapper, // Column-to-property mapping updateOf: updateOf, // Monitor specific columns for updates filter: filter, // WHERE clause filter notifyOn: DmlTriggerType.Insert | DmlTriggerType.Update, // DML operations to monitor executeUserPermissionCheck: true, // Check user permissions on start includeOldValues: true)) // Include old values in update notifications { dep.OnChanged += (sender, e) => Console.WriteLine($"Change detected: {e.ChangeType}"); dep.Start(); } ``` -------------------------------- ### Check Database Compatibility Version Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/blob/master/README.md Use this SQL script to determine the compatibility version of your database, which is essential for ensuring SqlTableDependency can track record changes. Execute this against the database you are monitoring. ```sql USE DECLARE @DBINFO TABLE ([ParentObject] VARCHAR(60),[Object] VARCHAR(60),[Field] VARCHAR(30),[VALUE] VARCHAR(4000)) INSERT INTO @DBINFO EXECUTE sp_executesql N'DBCC DBINFO WITH TABLERESULTS' SELECT [Field] ,[VALUE] ,CASE WHEN [VALUE] = 515 THEN 'SQL 7' WHEN [VALUE] = 539 THEN 'SQL 2000' WHEN [VALUE] IN (611,612) THEN 'SQL 2005' WHEN [VALUE] = 655 THEN 'SQL 2008' WHEN [VALUE] = 661 THEN 'SQL 2008R2' WHEN [VALUE] = 706 THEN 'SQL 2012' WHEN [VALUE] = 782 THEN 'SQL 2014' WHEN [VALUE] = 852 THEN 'SQL 2016' WHEN [VALUE] > 852 THEN '> SQL 2016' ELSE '?' END [SQLVersion] FROM @DBINFO WHERE [Field] IN ('dbi_createversion','dbi_version') ``` -------------------------------- ### Enable Service Broker for Database Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/blob/master/README.md Ensure Service Broker is enabled for your database to use notifications. This SQL command must be executed on the target database. ```sql ALTER DATABASE MyDatabase SET ENABLE_BROKER ``` -------------------------------- ### Define Customer C# Model Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Custom-map-between-model-property-and-table-column-using-ModelToTableMapper-T This C# class represents the Customer model, with property names differing from table column names. ```csharp public class Customer { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } } ``` -------------------------------- ### SqlTableDependency Basic Constructor Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Creates a SqlTableDependency instance using the basic constructor. The table name is inferred from the model class name. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Where; using System; using System.Linq.Expressions; // Define model matching your database table public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public int Quantity { get; set; } } // Basic constructor - model name matches table name var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var dep = new SqlTableDependency(connectionString)) { // Table name inferred from class name "Product" } ``` -------------------------------- ### Map Models with Data Annotations Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Use [Table] and [Column] attributes to define mappings between C# classes and database tables. Properties marked with [NotMapped] are ignored by the dependency monitor. ```csharp using TableDependency.SqlClient; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; // Use annotations to define table and column mappings [Table("user_accounts", Schema = "security")] public class UserAccount { [Key] [Column("user_id")] public int Id { get; set; } [Column("user_name")] public string Username { get; set; } [Column("email_address")] public string Email { get; set; } [Column("created_at")] public DateTime CreatedAt { get; set; } [NotMapped] // This property won't be monitored public string DisplayName => $"{Username} ({Email})"; } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; // SqlTableDependency automatically reads annotations // No need to specify tableName or mapper using (var tableDependency = new SqlTableDependency(connectionString)) { tableDependency.OnChanged += (sender, e) => { // Properties mapped from annotated columns Console.WriteLine($"User changed: {e.Entity.Username}"); Console.WriteLine($" Email: {e.Entity.Email}"); Console.WriteLine($" Created: {e.Entity.CreatedAt}"); }; tableDependency.Start(); Console.ReadKey(); } ``` -------------------------------- ### Configure Advanced SqlTableDependency Properties Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Configure settings such as database logging, culture, encoding, and tracing to customize the behavior of the dependency monitor. ```csharp using TableDependency.SqlClient; using System; using System.Diagnostics; using System.Globalization; using System.Text; public class Product { public int Id { get; set; } public string Name { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var tableDependency = new SqlTableDependency(connectionString)) { // Enable database logging (requires sysadmin or ALTER TRACE permission) tableDependency.ActivateDatabaseLogging = true; // Specify service broker authorization // tableDependency.ServiceAuthorization = "dbo"; // Queue execution context (default is "SELF") tableDependency.QueueExecuteAs = "SELF"; // Set encoding for message serialization (default: Unicode) tableDependency.Encoding = Encoding.UTF8; // Set culture for parsing values (affects dates, numbers) tableDependency.CultureInfo = CultureInfo.InvariantCulture; // Enable tracing for debugging tableDependency.TraceLevel = TraceLevel.Verbose; tableDependency.TraceListener = new ConsoleTraceListener(); // Read-only properties Console.WriteLine($"Table: {tableDependency.TableName}"); Console.WriteLine($"Schema: {tableDependency.SchemaName}"); Console.WriteLine($"DB Objects Naming: {tableDependency.DataBaseObjectsNamingConvention}"); tableDependency.OnChanged += (s, e) => Console.WriteLine($"Changed: {e.Entity.Name}"); tableDependency.Start(); Console.ReadKey(); } ``` -------------------------------- ### Define Customer Table Schema Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Custom-map-between-model-property-and-table-column-using-ModelToTableMapper-T This SQL script defines the structure of the Customer table in the database. ```sql CREATE TABLE [Customer] ( [Id] [int] IDENTITY(1, 1) NOT NULL, [First Name] [varchar](50) NULL, [Last Name] [varchar](50) NULL) ``` -------------------------------- ### Set Database Trustworthy ON Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/blob/master/README.md If using SqlTableDependency's QueueExecuteAs property other than 'SELF', it may be necessary to set the database's TRUSTWORTHY property to ON. This SQL command must be executed on the target database. ```sql ALTER DATABASE MyDatabase SET TRUSTWORTHY ON ``` -------------------------------- ### Map C# Model with Data Annotations Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Code-First-Data-Annotations-to-map-model-with-database-table Use Table and Column attributes to map a C# class to a specific SQL table and schema. ```C# [Table("Items", Schema = "Transaction")] public class Item { public Guid TransactionItemId { get; set; } [Column("Description")] public string Desc { get; set; } } ``` -------------------------------- ### Continue Tracking Table Changes After Host Restart (C#) Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Configure SqlTableDependency to not drop database objects on stop, allowing it to resume tracking changes from a queue when the host restarts. Use the 'namingForObjectsAlreadyExisting' parameter with the convention name obtained from a previous instance. ```C# string sqlTableDependencyDbObjectsName = null; try { // Specifying teardown = false we will say SqlTableDependecy do NOT drops // database QUEUE, TRIGGER and related batabase objects. tableDependency = new SqlTableDependency(ConnectionString, teardown: false); tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); sqlTableDependencyDbObjectsName = tableDependency.DataBaseObjectsNamingConvention; Console.WriteLine(@"Waiting for receiving notifications..."); Console.WriteLine(@"Press a key to stop"); Console.ReadKey(); } finally { tableDependency?.Dispose(); } .... // Table recod changes happening here will be stored in // SqlTableDependecy database QUEUE... .... // To retrieve changes happened when SqlTableDependency was down, // set namingForObjectsAlreadyExisting contructor parameter to naming convention get // from DataBaseObjectsNamingConvention property: try { // Specifying teardown = false we will say SqlTableDependecy do NOT drops // database QUEUE, TRIGGER and related batabase objects. tableDependency = new SqlTableDependency(ConnectionString, namingForObjectsAlreadyExisting: sqlTableDependencyDbObjectsName); tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); namingForObjectsAlreadyExisting = tableDependency.DataBaseObjectsNamingConvention; Console.WriteLine(@"Waiting for receiving notifications..."); Console.WriteLine(@"Press a key to stop"); Console.ReadKey(); } finally { tableDependency?.Dispose(); } ``` -------------------------------- ### Reuse Database Objects with Custom Naming in C# Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Initialize SqlTableDependency using a custom naming convention to reuse existing Service Broker and Queue objects. Set DatabaseObjectsTeardown to false to prevent their removal upon disposal. ```csharp var namingToUse = "CustomNaming"; var mapper = new ModelToTableMapper(); mapper.AddMapping(c => c.Name, "FIRST name").AddMapping(c => c.Surname, "Second Name"); using (var tableDependency = new SqlTableDependency(ConnectionString, TableName, mapper, null, false, namingToUse)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); .... } ``` -------------------------------- ### Define C# Model for Customers Table Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Model-and-properties-with-same-name-of-table-and-columns Represents the 'Customers' table structure in C# for use with SqlTableDependency. Properties not matching table columns are ignored. ```C# public class Customers { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public DateTime Born { get; set; } public int Quantity { get; set; } } ``` -------------------------------- ### Log SqlTableDependency to File Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Logging Configure SqlTableDependency to log verbose trace information to a specified file using a TextWriterTraceListener. ```C# var tableDependency = new SqlTableDependency(connectionString); tableDependency.OnChanged += this.TableDependency_Changed; tableDependency.TraceLevel = TraceLevel.Verbose; tableDependency.TraceListener = new TextWriterTraceListener(File.Create("c:\\temp\\output.txt")); tableDependency.Start(); ... ``` -------------------------------- ### Implement SqlTableDependency Notifications Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Code-First-Data-Annotations-to-map-model-with-database-table Configure the SqlTableDependency to monitor changes and handle the OnChanged event. ```C# using(var tableDependency = new SqlTableDependency(_connectionString)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); Console.WriteLine("Waiting for receiving notifications..."); Console.WriteLine("Press a key to stop"); Console.ReadKey(); } ... ... void TableDependency_Changed(object sender, RecordChangedEventArgs e) { if (e.ChangeType != ChangeType.None) { var changedEntity = e.Entity; Console.WriteLine("DML operation: " + e.ChangeType); Console.WriteLine("ID: " + changedEntity.TransactionItemId); Console.WriteLine("Description: " + changedEntity.Desc); } } ``` -------------------------------- ### Specify Naming Convention for Database Objects in C# Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes When restarting an application, specify the same database object naming convention used during initialization. SqlTableDependency will detect and use existing objects or create new ones if they are not found. ```csharp var namingToUse = "CustomNaming"; ``` -------------------------------- ### Model with DataAnnotations in C# Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Define a model class with System.ComponentModel.DataAnnotations attributes like [Table] and [Column] to map to database tables and columns. This allows SqlTableDependency to infer table and column names. ```csharp [Table("Customers")] public class Client { public long Id { get; set; } public string Name { get; set; } [Column("Surname")] public string FamilyName { get; set; } } ``` -------------------------------- ### Define Table Schema Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Specify-for-which-properties-we-want-receive-notification-using-UpdateOfModel-T--mapper This SQL statement defines the schema for the 'Person' table, including columns for Id, Name, Surname, and Born. ```SQL CREATE TABLE [Person]( [Id][int] IDENTITY(1, 1) NOT NULL, [Name] [nvarchar](50) NOT NULL, [Surname] [nvarchar](50) NOT NULL, [Born] [datetime] NULL) ``` -------------------------------- ### Handle Status Changes in SqlTableDependency (C#) Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Implement event handling for status changes in SqlTableDependency. This snippet shows how to subscribe to the 'OnStatusChanged' event and start/stop the dependency. ```C# using (var tableDependency = new SqlTableDependency(connectionString, "FlightBookings")) { tableDependency.OnStatusChanged += TableDependency_OnStatusChanged; tableDependency.Start(); Console.WriteLine(@"Waiting for receiving notifications..."); Console.WriteLine(@"Press a key to stop"); Console.ReadKey(); tableDependency.Stop(); } private static void TableDependency_OnStatusChanged(object sender, StatusChangedEventArgs e) { Console.WriteLine(@"Status: " + e.Status); } ``` -------------------------------- ### Log SqlTableDependency to Console Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Logging Configure SqlTableDependency to log verbose trace information to the console using a TextWriterTraceListener. ```C# var tableDependency = new SqlTableDependency(connectionString); tableDependency.OnChanged += this.TableDependency_Changed; tableDependency.TraceLevel = TraceLevel.Verbose; tableDependency.TraceListener = new TextWriterTraceListener(Console.Out); tableDependency.Start(); ... ``` -------------------------------- ### Set up TableDependency for Notifications Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Status-change Configure SqlTableDependency to listen for changes and status updates on a specific table. Ensure you have the necessary connection string and event handlers defined. ```C# var tableDependency = new SqlTableDependency(connectionString); tableDependency.OnChanged += this.TableDependency_Changed; tableDependency.OnStatusChanged += this.TableDependency_OnStatusChanged; tableDependency.Start(); ``` ```C# private static void TableDependency_OnStatusChanged(object sender, StatusChangedEventArgs e) { Console.WriteLine(@"Status: " + e.Status); } ``` -------------------------------- ### Define Model Class Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Specify-for-which-properties-we-want-receive-notification-using-UpdateOfModel-T--mapper This C# class represents the 'Person' entity, mapping to the columns in the 'Person' database table. ```C# public class Person { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } } ``` -------------------------------- ### Handle Table Record Changes with OnChanged Event Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Use the OnChanged event to react to Insert, Update, and Delete operations on a table. Set includeOldValues to true to access previous data during updates. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Base.EventArgs; using System; public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; // Include old values to track what changed during updates using (var tableDependency = new SqlTableDependency(connectionString, includeOldValues: true)) { tableDependency.OnChanged += OnTableChanged; tableDependency.Start(); Console.WriteLine("Monitoring Customer table..."); Console.ReadKey(); } void OnTableChanged(object sender, RecordChangedEventArgs e) { var entity = e.Entity; switch (e.ChangeType) { case ChangeType.Insert: Console.WriteLine($"New customer inserted:"); Console.WriteLine($" ID: {entity.Id}"); Console.WriteLine($" Name: {entity.FirstName} {entity.LastName}"); Console.WriteLine($" Email: {entity.Email}"); break; case ChangeType.Update: Console.WriteLine($"Customer {entity.Id} updated:"); Console.WriteLine($" New Name: {entity.FirstName} {entity.LastName}"); // Access old values (only available when includeOldValues: true) if (e.EntityOldValues != null) { Console.WriteLine($" Old Name: {e.EntityOldValues.FirstName} {e.EntityOldValues.LastName}"); } break; case ChangeType.Delete: Console.WriteLine($"Customer deleted:"); Console.WriteLine($" ID: {entity.Id}"); Console.WriteLine($" Name: {entity.FirstName} {entity.LastName}"); break; } } ``` -------------------------------- ### Implement Custom ITableDependencyFilter Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Where-filter Create a custom class that implements ITableDependencyFilter to define a T-SQL WHERE condition. This allows for more complex filtering logic. ```csharp public class CustomSqlTableDependencyFilter : ITableDependencyFilter { private readonly int _id; public CustomSqlTableDependencyFilter(int id) { _id = id; } public string Translate() { return "[Id] = " + _id; } } ``` -------------------------------- ### Implement Error Handling for SqlTableDependency Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Get-errors Subscribe to the OnError event to capture and handle exceptions thrown by the SqlTableDependency instance. ```C# var tableDependency = new SqlTableDependency(connectionString); tableDependency.OnChanged += this.TableDependency_Changed; tableDependency.OnError += this.TableDependency_OnError; tableDependency.Start(); ... private void TableDependency_OnError(object sender, ErrorEventArgs e) { throw e.Error; } ``` -------------------------------- ### OnChanged Event Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Handles table record changes, providing details about inserts, updates, and deletes. It can also include old values for update operations. ```APIDOC ## OnChanged Event The primary event fired when a table record changes. The RecordChangedEventArgs contains the change type (Insert, Update, Delete), the changed entity with current values, and optionally the entity with old values for update operations. ### Method Event Handler ### Parameters - **sender**: object - The object that raised the event. - **e**: RecordChangedEventArgs - An object containing event data. - **e.ChangeType**: ChangeType - The type of change (Insert, Update, Delete). - **e.Entity**: T - The changed entity with current values. - **e.EntityOldValues**: T (optional) - The entity with old values (available when includeOldValues is true). ### Request Example ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base.Enums; using TableDependency.SqlClient.Base.EventArgs; using System; public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; // Include old values to track what changed during updates using (var tableDependency = new SqlTableDependency(connectionString, includeOldValues: true)) { tableDependency.OnChanged += OnTableChanged; tableDependency.Start(); Console.WriteLine("Monitoring Customer table..."); Console.ReadKey(); } void OnTableChanged(object sender, RecordChangedEventArgs e) { var entity = e.Entity; switch (e.ChangeType) { case ChangeType.Insert: Console.WriteLine($"New customer inserted:"); Console.WriteLine($" ID: {entity.Id}"); Console.WriteLine($" Name: {entity.FirstName} {entity.LastName}"); Console.WriteLine($" Email: {entity.Email}"); break; case ChangeType.Update: Console.WriteLine($"Customer {entity.Id} updated:"); Console.WriteLine($" New Name: {entity.FirstName} {entity.LastName}"); // Access old values (only available when includeOldValues: true) if (e.EntityOldValues != null) { Console.WriteLine($" Old Name: {e.EntityOldValues.FirstName} {e.EntityOldValues.LastName}"); } break; case ChangeType.Delete: Console.WriteLine($"Customer deleted:"); Console.WriteLine($" ID: {entity.Id}"); Console.WriteLine($" Name: {entity.FirstName} {entity.LastName}"); break; } } ``` ``` -------------------------------- ### Configure DML Trigger Type in C# Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Release-Notes Initialize SqlTableDependency to receive notifications for specific DML operations like INSERT and UPDATE. Ensure the model and table name are correctly specified. ```csharp SqlTableDependency tableDependency = new SqlTableDependency( ConnectionString, TableName, mapper, (IList)null, DmlTriggerType.Insert | DmlTriggerType.Update, true); ``` -------------------------------- ### Handle SQL Server Table Change Errors Source: https://context7.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/llms.txt Implement the OnError event handler to gracefully manage exceptions during table monitoring. This allows for logging errors and implementing reconnection strategies. ```csharp using TableDependency.SqlClient; using TableDependency.SqlClient.Base.EventArgs; using System; public class Transaction { public int Id { get; set; } public decimal Amount { get; set; } } var connectionString = "data source=.;initial catalog=MyDB;integrated security=True"; using (var tableDependency = new SqlTableDependency(connectionString)) { tableDependency.OnChanged += (s, e) => Console.WriteLine($"Transaction: {e.ChangeType}"); tableDependency.OnError += (sender, e) => { Console.WriteLine($"Error occurred: {e.Error.Message}"); Console.WriteLine($"Stack Trace: {e.Error.StackTrace}"); // Log to your logging system // LogError(e.Error); // Optionally implement reconnection logic // ScheduleReconnect(); }; tableDependency.Start(); Console.ReadKey(); } ``` -------------------------------- ### Define C# Model for SqlTableDependency Source: https://github.com/isnemoequaltrue/monitor-table-change-with-sqltabledependency/wiki/Use-case:-Where-filter Define a C# class that maps to your database table. This model is used by SqlTableDependency to interact with the table. ```csharp public class Category { public int Id { get; set; } public string Code { get; set; } public decimal Price { get; set; } } ```