我在 MSSQL Server 中有一个数据库。我希望在特定表发生更改时收到通知,即插入和删除记录时,它会使用 SignalR hub 实时更新表,而无需刷新页面
我不知道如何创建包含数据库事件处理的类,就像它调用 SignalR hub 方法的每个数据更改一样。
ASP.NET Core 与 SQL Server 的实时数据更改通知
您可以尝试使用SqlDependency的OnChange事件来检测数据库更新,然后调用SignalR客户端方法来更新网页内容。
更多详细信息,请参考以下示例:
创建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");
}
}
注册 EmployeeRepository:
builder.Services.AddTransient<IEmployeeRepository, EmployeeRepository>();
@microsoft/signalr@latest
创建 SignalR Hub:
public class SignalServer : Hub
{
}
配置 SignalR:
builder.Services.AddSignalR();
...
app.MapHub<SignalServer>("/signalServer");
添加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)
}
})
}
})
在 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());
}
}
在员工索引页面:添加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>
}
最终结果如下: 工作流程: 页面加载时,signalr.js 文件中,会调用 Employee/GetEmployees 方法来显示员工,然后更新数据库时,SqlDependency 的 onchange 事件会检测到并显示调用signalR客户端函数重新加载员工列表。
问题是,如果你有 100 万行,你必须再次加载 100 万行,最好使用 sqldenpendencyEX