【问题标题】:.net core websockets obtain DbContext.net core websockets 获取 DbContext
【发布时间】:2017-04-24 00:58:19
【问题描述】:

我正在测试 .net core 并使用 .net core + 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
        }

    }
}

【问题讨论】:

  • 嗨,@John Smith。你解决了这个问题吗?我现在正在寻找解决方案
  • @Mergasov 是的,让我去代码,我会发布答案。

标签: c# asp.net entity-framework asp.net-core .net-core


【解决方案1】:

由于对这篇文章有一些兴趣,我添加了我使用的解决方案。

您可以通过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)) {

            }
        }

    }
}

【讨论】:

  • 你能提供一个例子来说明你如何使用缓存层来处理这个问题吗?
  • @jpdesigning 我无法真正提供代码,因为我无法再访问它了。我最终做的是有一个长时间运行的后台线程,它不时从线程安全队列中读取数据,并将来自该队列的更改保存到数据库中。 websocket 逻辑只是将信息传递到该队列。
猜你喜欢
  • 1970-01-01
  • 2019-03-10
  • 2018-10-12
  • 2016-07-23
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 2018-12-24
相关资源
最近更新 更多