目录
介绍
背景
使用代码
- 下载源代码 - 486.6 KB
在创建基于客户端服务器的 WPF 应用程序时,它可以让多个客户端连接到单个 WebApi 服务,我们需要解决的一个主要问题是在多个客户端应用程序之间同步数据。当连接的应用程序更改数据时,我们需要一种机制来使用刷新的数据更新胖客户端应用程序。SignalR 在这些场景中对推送通知非常有用。但它的另一个重要方面是跟踪所做的修改,以便可以将这些更新通知发送到其他连接的应用程序。
背景在我之前关于 SignalR 的文章中,我已经解释了如何通过使用 SignalR 来使 WPF 应用程序更具交互性和部署友好性。今天是领先一步,我们使用实体框架跟踪数据库更改,并使用 SignalR 将这些更改通知推送到客户端应用程序。
使用代码实体框架是当前数据访问的行业标准,我使用 EF 6 和 SignalR 创建了一个示例应用程序,以演示使用 SignalR 跟踪更改和通知。我们首先通过BaseContext(base DbContext) 类识别更改。这是应该由其他数据库/上下文类实现的类。我们重写该SaveChanges方法。使用该ProcessChnages方法识别和跟踪更改。对于跟踪的每个添加或修改,都会创建一个新的审计事件类型的实体,并将其添加到审计事务中。
public void ProcessChanges()
{
foreach (var ent in context.ChangeTracker.Entries()
.Where(p => p.State == EntityState.Deleted ||
p.State == EntityState.Modified || p.State == EntityState.Added))
{
//Set the update user/time
SetAuditTimestamps(ent);
if (ent.State == EntityState.Added)
{
//Save for processing later, when the ID is generated
AdditionEntities.Add(ent);
}
else
{
//Process now
ModifyEvents.Add(CreateAuditEvent(ent));
}
}
}
public void TrackModifications()
{
if (ModifyEvents.Count == 0 && AdditionEntities.Count == 0)
return;
this.auditTxn = new AuditTxn()
{
Date = DateTime.Now,
ServerName = Environment.MachineName,
AuditEvents = new List()
};
auditTxn.AuditEvents.AddRange(ModifyEvents);
context.Set().Add(auditTxn);
}
public void TrackAdditions()
{
if (ModifyEvents.Count == 0 && AdditionEntities.Count == 0)
return;
auditTxn.AuditEvents.AddRange(AdditionEntities.Select
(ae => CreateAuditEvent(ae, true)));
}
这些SignalRExtensions类包含将这些审计事件广播到连接的客户端的 SignalR 方法。该类包含一个ExcludeAuditEvents集合,当我们不想发送对某些域类进行修改的通知时,该集合可用于场景。
public static void BroadcastEntityUpdates(this T ctx) where T : IAuditableContext
{
var auditTxns = ctx.AuditTxns.Local;
var auditTxn = auditTxns.FirstOrDefault();
if (auditTxn == null)
{
return;
}
var context = GlobalHost.ConnectionManager.GetHubContext();
var notification = new EntityNotification()
{
AuditTxnId = auditTxn.AuditTxnId,
Date = auditTxn.Date,
ServerName = auditTxn.ServerName,
EntityEvents = auditTxn.AuditEvents.Where
(a => !ExcludedAuditEvents.Contains(a.ObjectType)).Select
(e => new EntityEvent()
{
AuditEventId = e.AuditEventId,
ObjectId = e.ObjectId,
ObjectType = e.ObjectType,
Payload = ctx.GetPayload(e),
EventType = e.EventType == AuditEventTypes.Added ?
UpdateTypes.Added : e.EventType == AuditEventTypes.Deleted ?
UpdateTypes.Deleted : UpdateTypes.Modified,
}).ToList()
};
context.Clients.All.UpdateEntities(notification);
}
现在客户端应用程序应该按照我之前的文章探索Signal-R让WPF应用程序交互中的说明工作,其中onmessage处理程序可以配置为使用ObjectId和ObjectType在EntityNotification类中传递来重新加载 EF 数据。
https://www.codeproject.com/Tips/5329997/Tracking-Changes-in-EntityFramework-and-Notifying