我有一个SignalR应用程序分为两部分。我在MVC应用程序(SignalR服务器)和Windows服务(SignalR客户端)之间来回传递基本消息。 Windows服务位于后端计算机上,该计算机上有AdventureWork2012数据库。管理层希望Windows服务 - SignalR客户端查询数据库并通过SignalR发回DataSet。 SignalR可以通过DataSet吗?我得到一个例外“无效的URI:Uri字符串太长了。”在我调用服务器方法的事件日志中。
这是MVC服务器中心:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Call Windows Service
string message1 = System.Environment.MachineName;
Clients.All.Notify(message1);
}
public void Register(string registrationID,string connectionID)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
System.Web.HttpContext.Current.Application["registrationID"] = registrationID + "|" + connectionID;
}
public void RecieveDataSet(DataSet ds)
{
Clients.All.addNewMessageToPage("Data Set recieved");
}
以下是在该行上引发异常的Windows服务代码:
await alphaProxy.Invoke("RecieveDataSet", employees);
代码是:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://www.someurl.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
await hubConnection.Start();
string cid = hubConnection.ConnectionId.ToString();
eventLog1.WriteEntry("ConnectionID: " + cid);
// Invoke method on hub
await alphaProxy.Invoke("Hello", "Message from Service - ConnectionID: " + cid + " - " + System.Environment.MachineName.ToString() + " " + DateTime.Now.ToString());
await
alphaProxy.Invoke("Register", "81577f58-0e05-43f4-b322-fbf0d9d1e79e",
hubConnection.ConnectionId.ToString());
alphaProxy.On("addNewMessageToPage", () => eventLog1.WriteEntry("Notified!"));
DataSet employees = new DataSet();
string connString = "...";
SqlConnection conn = new SqlConnection(connString);
string queryString = "SELECT * FROM [HumanResources].[Employee]";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, conn);
adapter.Fill(employees, "HumanResources.Employee");
await alphaProxy.Invoke("RecieveDataSet", employees);
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
是否可以传递DataSet?如果没有,我是否必须序列化/反序列化?如果是这样,你能展示代码吗?
答案 0 :(得分:3)
由于种种原因(尤其是通过背板向外扩展),您希望使用SignalR保持消息非常轻量级,因此我不会通过SignalR消息亲自传递像DataSet
这样的大事。我通常建议更大的有效负载是你发送一个特定的消息告诉浏览器它应该更新那些数据然后通过使用传统的GET下载到某种基于REST的服务。这样您就可以获得更新的实时通知,但是您使用传统的HTTP GET来传输实际的有效负载。
答案 1 :(得分:3)
我建议您将数据集转换为数据传输对象并传递它。使用SignalR,您可以传递每个对象,因为它是水合的,这样您不仅可以在获取时通知观察者,还可以在添加任何新项目时通知观察者。我没有测试过这段代码,所以我可能错过了一些东西,但它应该会给你一个想法。
adapter.Fill(employees, "HumanResources.Employee");
foreach (var dr in employees)
{
var empDto = new EmployeeDto
{
FirstName = dr.Fields("FirstName"),
LastName = dr.Fields("LastName"),
// Additional fields go here...
};
alphaProxy.Clients.ReceiveDataSet(empDto); // Serializes the dto as json by default.
}
当然,如果您想在回复中发送完整列表,您应该可以稍微修改一下:
adapter.Fill(employees, "HumanResources.Employee");
var items = new List<EmployeeDto>();
foreach (var dr in employees)
{
var empDto = new EmployeeDto
{
FirstName = dr.Fields("FirstName"),
LastName = dr.Fields("LastName"),
// Additional fields go here...
};
items.Add(empDto);
}
alphaProxy.Clients.ReceiveDataSet(items); // Serializes the dto as json array by default.
答案 2 :(得分:0)