目录
介绍
流程
步骤1:创建以下表
步骤2:创建一个存储过程
步骤3:创建一个作业
步骤4:创建SignalR集线器
步骤5:创建SignalR客户端
步骤6:在启动中注册SignalR
步骤7:创建集线器代理
步骤9:测试应用
结论
介绍通过我们的应用程序向我们的用户发送通知/提醒是我们的明显要求。这些通知可能是电子邮件、文本/语音消息等。我们有一些选项可用于自动化此过程,例如SQL Server中的数据库邮件(Internet上提供了链接以启用和配置),我们可以创建Windows服务或编写Application_Start方法和计时器可以在每天的某个时间完成这项工作。最近,我被要求每天早上7点自动向应用程序用户发送邮件和文本消息,无论他们是联机还是脱机。
我不想使用以上任何内容,因此决定使用SignalR,SqlTableDependency和SQL Agent。这个想法是创建一个单独的表来每天记录通知,因为该表是由SQL Agent作业处理的,因此SignalR客户端会初始化SqlTableDependency。它将获取记录并通过我们的ASP.NET应用程序发送邮件/文本消息。
流程上述解决方案仅在应用程序和服务器启动时才有效。我在这里分享了可用于执行类似任务的工作代码。
步骤1:创建以下表首先,我们将创建一些表来保存用户、任务等。
CREATE TABLE [dbo].[tblUser](
[UserId] [int] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
[Email] [nvarchar](500) NOT NULL,
[Mobile] [nvarchar](15) NOT NULL
)
CREATE TABLE [dbo].[tblTask](
[TaskId] [int] NOT NULL,
[TaskCode] [nvarchar](50) NOT NULL,
[TaskDate] [date] NULL,
[AssignedTo] [int] NOT NULL,
[Status] [nvarchar](50) NOT NULL,
[Message] [nvarchar](500) NULL,
[ReminderStart] [date] NOT NULL
)
CREATE TABLE [dbo].[tblDailyReminder](
[ReminderId] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NOT NULL,
[IsSent] [bit] NOT NULL CONSTRAINT [DF_tblDailyReminder_IsSent] _
DEFAULT ((0))
)
步骤2:创建一个存储过程
这是将由SQL代理每天执行的存储过程。在这里,我们正在获取一些待处理的任务,它们的提醒日期已经开始。
Create PROCEDURE [dbo].[sp_PushReminder]
AS
BEGIN
Delete From tblDailyReminder
Insert into tblDailyReminder(TaskId,IsSent)
Select TaskId,0 from tblTask _
where Status='Pending'and ReminderStart new ReminderClient
(GlobalHost.ConnectionManager.GetHubContext().Clients));
private static SqlTableDependency _sqltableDependency;
public Dictionary DictUsers = new Dictionary();
private ReminderClient(IHubConnectionContext clients) {
Clients = clients;
var mapper = new ModelToTableMapper();
mapper.AddMapping(s => s.TaskId, "TaskId");
mapper.AddMapping(s => s.ReminderId, "ReminderId");
_ sqltableDependency = new SqlTableDependency
(ConfigurationManager.ConnectionStrings["LocalConStr"].ConnectionString,
"tblDailyReminder", "", mapper);
_ sqltableDependency.OnChanged += SqlTableDependency_Changed;
_ sqltableDependency.OnError += SqlTableDependency_OnError;
_ sqltableDependency.Start();
}
public static ReminderClient Instance {
get {
return _instance.Value;
}
}
private IHubConnectionContext Clients {
get;
set;
}
void SqlTableDependency_OnError(object sender, ErrorEventArgs e) {
throw e.Error;
}
void SqlTableDependency_Changed(object sender,
RecordChangedEventArgs e) {
if (e.ChangeType == ChangeType.Insert)
{
NotificationDemoEntities notificationDemoEntities =
new NotificationDemoEntities();
var mailRecepients = notificationDemoEntities.tblDailyReminders.Where
(x => x.ReminderId == e.Entity.ReminderId).Include
(x => x.tblTask).Include(x => x.tblTask.tblUser).ToList();
if (mailRecepients != null && mailRecepients.Count() > 0)
{
SendMailNotification(mailRecepients.FirstOrDefault().tblTask.tblUser.Email,
mailRecepients.FirstOrDefault().tblTask.Message);
}
}
}
private void SendMailNotification(string Tomail, string message) {
try
{
MailMessage mailMessage = new MailMessage();
SmtpClient smtp = new SmtpClient();
mailMessage.From = new MailAddress("FromMailAddress");
mailMessage.To.Add(new MailAddress(Tomail));
mailMessage.Subject = "Test";
mailMessage.IsBodyHtml = true;
mailMessage.Body = message;
smtp.Port = 587;
smtp.Host = "smtp.gmail.com";
smtp.EnableSsl = true;
smtp.UseDefaultCredentials = false;
smtp.Credentials =
new NetworkCredential("FromMailAddress", "password");
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Send(mailMessage);
}
catch (Exception) {
}
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing) {
if (!disposedValue) {
if (disposing)
{
_sqltableDependency.Stop();
}
disposedValue = true;
}
}
~ReminderClient() {
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
步骤6:在启动中注册SignalR
确保将signalR映射到Startup类的Configuration方法中:
public class Startup{
public void Configuration(IAppBuilder app) {
app.MapSignalR();
}
}
步骤7:创建集线器代理
为了每次都能使用它,我们必须创建集线器的代理。我将在Global.asax类的Application_Start()方法中这样做。
protected void Application_Start(){
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
HubConnection hubConnection =
new HubConnection("http://localhost:55027/signalr/hubs");
hubProxy = hubConnection.CreateHubProxy("ReminderHub");
hubConnection.Start();
}
步骤9:测试应用
为了进行测试,我们需要手动执行作业。
右键单击该作业,然后开始该作业。工作完成后,我们的代码将被执行,并通过邮件发送通知。
每天或按照您计划的时间执行同一作业。
参考资料
要了解有关SqlTableDependency的更多信息, 请访问 https://www.nuget.org/packages/SqlTableDependency。
结论我们可以使用上述技术将每日提醒发送给我们的用户。在这里,我们使用了SqlTableDependency对象来捕获数据库更改,并且我们还可以在发送邮件/消息的同时向用户推送应用程序级别的通知。我认为它也可以帮助其他开发人员。欢迎提出建议/查询。