{"id":21258154,"url":"https://github.com/isnemoequaltrue/blazor-notification-db-record-change","last_synced_at":"2025-07-11T02:32:18.928Z","repository":{"id":203697671,"uuid":"219354823","full_name":"IsNemoEqualTrue/blazor-notification-db-record-change","owner":"IsNemoEqualTrue","description":"Blazor notification on database recond changes","archived":false,"fork":false,"pushed_at":"2020-01-15T06:57:28.000Z","size":1078,"stargazers_count":39,"open_issues_count":3,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-05T19:34:06.607Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IsNemoEqualTrue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-11-03T19:36:34.000Z","updated_at":"2024-02-20T18:41:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"78d8b6cb-3182-4ed7-8602-f101f9e087c5","html_url":"https://github.com/IsNemoEqualTrue/blazor-notification-db-record-change","commit_stats":null,"previous_names":["christiandelbianco/blazor-notification-db-record-change","isnemoequaltrue/blazor-notification-db-record-change"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/IsNemoEqualTrue/blazor-notification-db-record-change","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsNemoEqualTrue%2Fblazor-notification-db-record-change","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsNemoEqualTrue%2Fblazor-notification-db-record-change/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsNemoEqualTrue%2Fblazor-notification-db-record-change/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsNemoEqualTrue%2Fblazor-notification-db-record-change/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IsNemoEqualTrue","download_url":"https://codeload.github.com/IsNemoEqualTrue/blazor-notification-db-record-change/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsNemoEqualTrue%2Fblazor-notification-db-record-change/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264712798,"owners_count":23652661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-21T04:07:19.590Z","updated_at":"2025-07-11T02:32:18.443Z","avatar_url":"https://github.com/IsNemoEqualTrue.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Blazor client notifications on database record change\nThis example uses .NET CORE 3.0 Blazor server side to real-time update a HTML page on any database record changes.\n\n\u003cimg src=\"https://github.com/christiandelbianco/blazor-notification-db-record-change/blob/master/Schema.png\" /\u003e\n\nBased on the observer design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. \n\n\u003cimg src=\"https://github.com/christiandelbianco/blazor-notification-db-record-change/blob/master/2019-11-03at21-05-44.gif\" /\u003e\n\n## Database table\nTable for which I want to receive notifications every time its content changes:\n\n```SQL\nCREATE TABLE [dbo].[WeatherForecasts](\n\t[City] [nvarchar](50) NOT NULL,\n\t[Temperature] [int] NOT NULL\n)\n```\n\n## Subject\nSingleton instance wrapping SqlTableDependency and forwarding record table changes to subscribers:\n\n```C#\n    public delegate void WeatherForecastDelegate(object sender, WeatherForecastChangeEventArgs args);\n\n    public class WeatherForecastChangeEventArgs : EventArgs\n    {\n        public WeatherForecast NewWeatherForecast { get; }\n        public WeatherForecast OldWeatherForecast { get; }\n\n        public WeatherForecastChangeEventArgs(WeatherForecast newWeatherForecast, WeatherForecast oldWeatherForecast)\n        {\n            this.NewWeatherForecast = newWeatherForecast;\n            this.OldWeatherForecast = oldWeatherForecast;\n        }\n    }\n\n    public interface IWeatherForecastService\n    {\n        public event WeatherForecastDelegate OnWeatherForecastChanged;\n        IList\u003cWeatherForecast\u003e GetForecast();\n    }\n\n    public class WeatherForecastService : IWeatherForecastService, IDisposable\n    {\n        private const string TableName = \"WeatherForecasts\";\n        private SqlTableDependency\u003cWeatherForecast\u003e _notifier;\n        private IConfiguration _configuration;\n        \n        public event WeatherForecastDelegate OnWeatherForecastChanged;\n\n        public WeatherForecastService(IConfiguration configuration)\n        {\n            _configuration = configuration;\n\n            _notifier = new SqlTableDependency\u003cWeatherForecast\u003e(_configuration[\"ConnectionString\"], TableName);\n            _notifier.OnChanged += this.TableDependency_Changed;\n            _notifier.Start();\n        }\n\n        private void TableDependency_Changed(object sender, RecordChangedEventArgs\u003cWeatherForecast\u003e e)\n        { \n            if (this.OnWeatherForecastChanged != null)\n            {\n                this.OnWeatherForecastChanged(this, new WeatherForecastChangeEventArgs(e.Entity, e.EntityOldValues));\n            }\n        }\n\n        public IList\u003cWeatherForecast\u003e GetForecast()\n        {\n            var result = new List\u003cWeatherForecast\u003e();\n\n            using (var sqlConnection = new SqlConnection(_configuration[\"ConnectionString\"]))\n            {\n                sqlConnection.Open();\n\n                using (var command = sqlConnection.CreateCommand())\n                {\n                    command.CommandText = \"SELECT * FROM \" + TableName;\n                    command.CommandType = CommandType.Text;\n\n                    using (SqlDataReader reader = command.ExecuteReader())\n                    {\n                        if (reader.HasRows)\n                        {\n                            while (reader.Read())\n                            {\n                                result.Add(new WeatherForecast\n                                {\n                                    City = reader.GetString(reader.GetOrdinal(\"City\")),\n                                    Temperature = reader.GetInt32(reader.GetOrdinal(\"Temperature\"))\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n\n            return result;\n        }\n\n        public void Dispose()\n        {\n            _notifier.Stop();\n            _notifier.Dispose();\n        }\n    }\n```\n\nRegistration as Singleton:\n\n```C#\npublic void ConfigureServices(IServiceCollection services)\n{\n    ...\n    ...\n    services.AddSingleton\u003cIWeatherForecastService, WeatherForecastService\u003e();\n}\n```\n\n## Observer\nIndex.razor page code (event subscriber):\n\n```C#\n@page \"/\"\n\n@using DataBaseRecordChaneNotificationWithBlazor.Data\n\n@inject IWeatherForecastService ForecastService\n@implements IDisposable\n\n\u003ch1\u003eWeather forecast\u003c/h1\u003e\n\n\u003cp\u003eImmediate client notification on record table change with Blazor\u003c/p\u003e\n\n\u003ctable class=\"table\"\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth\u003eCity\u003c/th\u003e\n            \u003cth\u003eTemp. (C)\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        @foreach (var forecast in forecasts)\n        {\n            \u003ctr\u003e\n                \u003ctd\u003e@forecast.City\u003c/td\u003e\n                \u003ctd\u003e@forecast.Temperature\u003c/td\u003e\n            \u003c/tr\u003e\n        }\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n@code {\n    IList\u003cWeatherForecast\u003e forecasts;\n\n    protected override void OnInitialized()\n    {\n        this.ForecastService.OnWeatherForecastChanged += this.WeatherForecastChanged;\n        this.forecasts = this.ForecastService.GetForecast();\n    }\n\n    private async void WeatherForecastChanged(object sender, WeatherForecastChangeEventArgs args)\n    {\n        var recordToupdate = this.forecasts.FirstOrDefault(x =\u003e x.City == args.NewWeatherForecast.City);\n        if (recordToupdate == null)\n        {\n            this.forecasts.Add(args.NewWeatherForecast);\n        }\n        else\n        {\n            recordToupdate.Temperature = args.NewWeatherForecast.Temperature;\n        }\n\n        await InvokeAsync(() =\u003e\n        {\n            base.StateHasChanged();\n        });\n    }\n\n    public void Dispose()\n    {\n        this.ForecastService.OnWeatherForecastChanged += this.WeatherForecastChanged;\n    }\n}\n```\n\nMore info on https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisnemoequaltrue%2Fblazor-notification-db-record-change","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisnemoequaltrue%2Fblazor-notification-db-record-change","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisnemoequaltrue%2Fblazor-notification-db-record-change/lists"}