ASP.NET Core 与 MSSQL Server 的实时数据更改通知

问题描述 投票:0回答:2

我在 MSSQL Server 中有一个数据库。我希望在特定表发生更改时收到通知,即插入和删除记录时,它会使用 SignalR hub 实时更新表,而无需刷新页面

我不知道如何创建包含数据库事件处理的类,就像它调用 SignalR hub 方法的每个数据更改一样。

database asp.net-core sql-server-2008 asp.net-core-signalr
2个回答
1
投票

ASP.NET Core 与 SQL Server 的实时数据更改通知

您可以尝试使用SqlDependency的OnChange事件来检测数据库更新,然后调用SignalR客户端方法来更新网页内容。

更多详细信息,请参考以下示例:

    1. 创建一个asp.net core MVC应用程序,并添加一个带有以下测试数据的Employee模型:

    enter image description here

  1. 创建EmployeeRepository:在SqlDependency onchange事件中,调用singalR客户端方法并更新内容。

 public interface IEmployeeRepository
 {
     List<Employee> GetAllEmployees();
 }
 public class EmployeeRepository : IEmployeeRepository
 {
     private readonly IHubContext<SignalServer> _context;
     string connectionString = "";
     public EmployeeRepository(IConfiguration configuration, IHubContext<SignalServer> context)
     {
         connectionString = configuration.GetConnectionString("DefaultConnection");
         _context = context;
     }
     public List<Employee> GetAllEmployees()
     {
         var employees = new List<Employee>();

         using (SqlConnection conn = new SqlConnection(connectionString))
         {
             conn.Open();

             SqlDependency.Start(connectionString);

             string commandText = "select Id, Name, Age from dbo.Employees";

             SqlCommand cmd = new SqlCommand(commandText, conn);

             SqlDependency dependency = new SqlDependency(cmd);

             dependency.OnChange+=new OnChangeEventHandler(dbChangeNotification);

             var reader = cmd.ExecuteReader();

             while (reader.Read())
             {
                 var employee = new Employee
                 {
                     Id = Convert.ToInt32(reader["Id"]),
                     Name = reader["Name"].ToString(),
                     Age = Convert.ToInt32(reader["Age"])
                 };

                 employees.Add(employee);
             }
         }
         return employees;
     }

     private void dbChangeNotification(object sender, SqlNotificationEventArgs e)
     {
         _context.Clients.All.SendAsync("refreshEmployees");
     }
 }
  1. 注册 EmployeeRepository:

    builder.Services.AddTransient<IEmployeeRepository, EmployeeRepository>();
    
  2. 添加 SignalR 客户端库

    @microsoft/signalr@latest

  3. 创建 SignalR Hub:

     public class SignalServer : Hub
     {
    
     }
    
  4. 配置 SignalR:

    builder.Services.AddSignalR();
    ...
    app.MapHub<SignalServer>("/signalServer");
    
  5. 添加SignalR客户端脚本(signalr.js):

     $(() => {
         //build the hub connection
         let connection = new signalR.HubConnectionBuilder().withUrl("/signalServer").build() 
         connection.start() 
         connection.on("refreshEmployees", function () {
             loadData() //after database change, it will call this function to refresh the data.
         }) 
         loadData(); //when page load call the loadData method to display the data. 
         function loadData() {
             var tr = ''
    
             $.ajax({
                 url: '/Employee/GetEmployees',
                 method: 'GET',
                 success: (result) => {
                     $.each(result, (k, v) => {
                         tr = tr + `<tr>
                             <td>${v.id}</td>
                             <td>${v.name}</td>
                             <td>${v.age}</td>
                         </tr>`
                     })
    
                     $("#tableBody").html(tr)
                 },
                 error: (error) => {
                     console.log(error)
                 }
             })
         }
     }) 
    
  6. 在 EmployeeControler 中:

     public class EmployeeController : Controller
     {
         private readonly IEmployeeRepository _repository;
    
         public EmployeeController(IEmployeeRepository repository)
         {
             _repository = repository;
         }
         public IActionResult Index()
         {
             return View();
         }
         [HttpGet]
         public IActionResult GetEmployees()
         {
             return Ok(_repository.GetAllEmployees());
         }
    
     }
    
  7. 在员工索引页面:添加singalr客户端引用。

    <table class="table">
         <thead>
             <tr>
                 <th>Id</th>
                 <th>Name</th>
                 <th>Age</th>
             </tr>
         </thead>
         <tbody id="tableBody">
         </tbody>
     </table>
     @section Scripts{
         <script src="~/js/signalr/dist/browser/signalr.js"></script>
         <script src="~/js/signalr.js"></script>
     }
    

    enter image description here

最终结果如下: 工作流程: 页面加载时,signalr.js 文件中,会调用 Employee/GetEmployees 方法来显示员工,然后更新数据库时,SqlDependency 的 onchange 事件会检测到并显示调用signalR客户端函数重新加载员工列表。

enter image description here


0
投票

问题是,如果你有 100 万行,你必须再次加载 100 万行,最好使用 sqldenpendencyEX

© www.soinside.com 2019 - 2024. All rights reserved.