我正在测试.net核心并使用.net核心websockets制作一个小样本应用程序将一些数据推送到我的应用程序中.我想使用dbcontext将此数据保存在数据库中.
但是我在我的websocket处理程序中获取dbcontext时遇到了问题.那么我该如何创建一个dbcontext来使用呢.
我的启动配置方法包含:
...
app.Map("/ws", WSHandler.Map);
...
这是我的WSHandler类,它实现了从传入连接中实际读取.我需要一个DbContext,我可以用来从数据库读/写.
/// <summary>
/// Handler for an incoming websocket client
/// </summary>
public class WSHandler {
/// <summary>
/// Max size in bytes of an incoming/outgoing message
/// </summary>
public const int BufferSize = 4096;
/// <summary>
/// The socket of the current connection
/// </summary>
WebSocket socket;
/// <summary>
/// Constructor, assign socket to current instance and adds socket to ConnectedClients.
/// </summary>
/// <param name="socket"></param>
WSHandler(WebSocket socket) {
this.socket = socket;
}
/// <summary>
/// Configure app to use websockets and register handler.
/// </summary>
/// <param name="app"></param>
public static void Map(IApplicationBuilder app) {
app.UseWebSockets();
app.Use((WSHandler.Acceptor);
}
/// <summary>
/// Accept HttpContext and handles constructs instance of WSHandler.
/// </summary>
/// <param name="hc">The HttpContext</param>
/// <param name="n">Task n</param>
/// <returns></returns>
static async Task Acceptor(HttpContext hc, Func<Task> n) {
if (hc.WebSockets.IsWebSocketRequest == false) {
return;
}
var socket = await hc.WebSockets.AcceptWebSocketAsync();
var h = new WSHandler(socket);
await h.Loop();
}
/// <summary>
/// Wait's for incoming messages
/// </summary>
/// <returns></returns>
async Task Loop() {
var buffer = new Byte[BufferSize];
ArraySegment<Byte> segment = new ArraySegment<byte>(buffer);
while (this.socket.State == WebSocketState.Open) {
WebSocketReceiveResult result = null;
do {
result = await socket.ReceiveAsync(segment, CancellationToken.None);
} while (result.EndOfMessage == false);
// do something with message here. I want to save parse and save to database
}
}
}
最佳答案 由于在这篇文章中有一些兴趣,我添加了我使用的解决方案.
您可以通过HttpContext访问所有服务.所以我做的是从这个服务获取上下文选项,然后在需要时创建上下文.请注意,虽然不建议长时间生活上下文,但如果发生错误,则DbContext不再可用.最后,我实现了一个不同的数据库缓存层并写入,而不是在websocket处理程序中使用DbContext本身.
以下是扩展为创建DbContexts的代码.我没有测试过,因为我现在还没有可用的视觉工作室……
<summary>
/// Handler for an incoming websocket client
/// </summary>
public class WSHandler {
/// <summary>
/// Max size in bytes of an incoming/outgoing message
/// </summary>
public const int BufferSize = 4096;
/// <summary>
/// The socket of the current connection
/// </summary>
WebSocket socket;
/// <summary>
/// The options to create DbContexts with.
/// </summary>
DbContextOptions<AssemblyServerContext> ctxOpts;
/// <summary>
/// Constructor, assign socket to current instance and adds socket to ConnectedClients.
/// </summary>
/// <param name="socket"></param>
/// <param name="ctxOpts"></param>
WSHandler(WebSocket socket, DbContextOptions<AssemblyServerContext> ctxOpts) {
this.ctxOpts = ctxOpts;
this.socket = socket;
}
/// <summary>
/// Configure app to use websockets and register handler.
/// </summary>
/// <param name="app"></param>
public static void Map(IApplicationBuilder app) {
app.UseWebSockets();
app.Use((WSHandler.Acceptor);
}
/// <summary>
/// Accept HttpContext and handles constructs instance of WSHandler.
/// </summary>
/// <param name="hc">The HttpContext</param>
/// <param name="n">Task n</param>
/// <returns></returns>
static async Task Acceptor(HttpContext hc, Func<Task> n) {
if (hc.WebSockets.IsWebSocketRequest == false) {
return;
}
var socket = await hc.WebSockets.AcceptWebSocketAsync();
var ctxOptions = hc.RequestServices.GetService<DbContextOptions<AssemblyServerContext>>();
var h = new WSHandler(socket, ctxOptions);
await h.Loop();
}
/// <summary>
/// Wait's for incoming messages
/// </summary>
/// <returns></returns>
async Task Loop() {
var buffer = new Byte[BufferSize];
ArraySegment<Byte> segment = new ArraySegment<byte>(buffer);
while (this.socket.State == WebSocketState.Open) {
WebSocketReceiveResult result = null;
do {
result = await socket.ReceiveAsync(segment, CancellationToken.None);
} while (result.EndOfMessage == false);
// do something with message here. I want to save parse and save to database
using (var ctx = new AssemblyServerContext(ctxOpts)) {
}
}
}
}