使用SignalR将数据从SQL Server推送到Web应用程序

9
我的 ASP.NET MVC 4 Web 应用程序向客户端显示频繁更新的数据。数据来自外部源(安装在服务器上的应用程序),并由 SQL Server 2008 R2 处理。
目前,数据流相当传统:客户端从 ASP.NET 轮询,而 ASP.NET 再从 SQL Server 轮询。
为了避免轮询(现在我需要 Web 应用程序用户之间的实时交互),我正在改变方法以使用 signalR 进行推送,将数据广播给客户端。这增加了用户体验的流畅度,并减少了客户端和 ASP.NET 服务器之间轮询的开销。
问题在于反转 SSRV 和 ASP.NET 之间的流程:我想以最有效的方式从 SSRV 推送数据到 ASP.NET。
SSRV 正在运行昂贵的查询以导入一些外部数据 - 一旦数据被处理,它们也准备通过广播共享到互联网上。
我的当前简陋方法:向 Web 应用程序发出 POST Http 请求(在本地主机上)以发送数据(我使用 CLR 函数进行操作)。
一旦数据被处理,我将它们打包好准备使用 HttpWebRequest,将它们排队在服务代理中,以避免影响其他活动,然后完成操作。
我已经放弃了 SqlDependency,因为它会强制我查询数据 - 这不是一个很大的优势(我会用在 SQL Server 上运行的查询代替本地主机 HTTP 请求)。
同时,我感觉应该有更简洁的方法来完成这个功能。您有什么建议吗?
2个回答

7

很遗憾,我有点晚意识到SignalR.Client.NET.35库的存在。

在撰写本文时,它并没有被打包到NuGet中,因此必须从GitHub SignalR项目网站下载代码,并将其作为项目添加到解决方案中(需要同时添加SignalR.Client.NETSignalR.Client.NET35)。

以下是最终解决方案,希望能对未来的某些人有所帮助:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Xml;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Net;
using System.IO;
using System.Xml.XPath;
using SignalR.Client.Hubs;

    internal static HubConnection connectionT = null;
    internal static IHubProxy msgHubT = null;

    /// <summary>
    /// allows SSRV to send a message to the Web Socket hub
    /// </summary>
    /// <param name="URL">URL of the Hub</param>
    /// <param name="hubName">Name of the message Hub to be used for broadcasting.</param>
    /// <param name="hubMethod">Hub method to be used for broadcasting.</param>
    /// <param name="message">Message to be broadcasted.</param>
    [SqlFunction()]
    public static void ut_sendMsgToHub(string URL, string hubName, string hubMethod, string message)
    { 
      try
        {
        if (connectionT == null)
        {
            connectionT = new HubConnection(URL.Trim()); // "http://localhost:56844/M2Hub"
        }
        if (msgHubT == null)
        {
            msgHubT = connectionT.CreateProxy(hubName.Trim());//"M2data"
        }

            if (!(connectionT.State == SignalR.Client.ConnectionState.Connected 
                || connectionT.State == SignalR.Client.ConnectionState.Reconnecting
                 || connectionT.State == SignalR.Client.ConnectionState.Connecting))
                connectionT.Start().Wait();
            msgHubT.Invoke(hubMethod.Trim(), message.Trim()).Wait();//"Send"
        }
        catch (Exception exc)
        {
            SqlContext.Pipe.Send("ut_sendMsgToHub error: " + exc.Message + Environment.NewLine);
        }
    }

重要提示: 与编译好的SQL SERVER 2008R2 CLR库一起,您需要将以下DLL文件放置在同一个文件夹中:
  • Newtonsoft.Json
  • SignalR.Client.Net35 (显然)
  • SMdiagnostics
  • System.Runtime.Serialization
  • System.ServiceModel(如果不兼容,请参考C:\ Windows \ assembly中GAC中的版本号)。
  • System.Threading

最后,在SQL SERVER中进行如下操作:

CREATE ASSEMBLY CLR_Bridge from 'C:\PathToLibraries\Library_CLR.dll' 
WITH PERMISSION_SET = UNSAFE --UNSAFE required
CREATE PROCEDURE ut_sendMsgToHub 
@url nchar(125) ,
@hubName nchar(75),
@hubMethod NCHAR(75),
@message NVARCHAR(MAX)
AS
EXTERNAL NAME CLR_Bridge.[LibraryNamespace.CLR_Bridge].ut_sendMsgToHub 

为了调用 ut_sendMsgToHub 函数,我使用服务代理,以确保函数执行中出现的任何问题与处理数据的存储过程解耦。

1
SignalR 的团队友善地提供了一些对比普通 POST 方法的评论,你可以在这里阅读整个讨论串:链接 - eddo
您是否直接从 SQL Server 的 CLR DLL(SignalR 服务器)向 SignalR 客户端提供数据?这个 DLL 是哪种 VS 项目类型?是类库还是 SQL Server 数据库项目? - ibubi

1
你看过SignalR吗?你可以使用它来异步地向你的UI推送数据(虽然它不是真正的推送)。这可能对于你的特定情况不可接受,但我建议你去看一下。也许这就是你需要的。希望能有所帮助。

1
正如我之前所写的,我已经在使用SignalR了,问题是SSRV和Web应用程序服务器之间的数据流,而不是Web应用程序服务器和客户端之间的数据流... - eddo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接