实体框架。刷新上下文

时间:2019-05-03 03:33:04

标签: entity-framework asp.net-core signalr

我是C#的初学者。请帮助我前进。我有控制台应用程序,可以对数据库进行更改。我想通过Web服务显示信息。我已经通过EntityFrameworkCore与DB链接,对于在线流数据,我选择了SignalR。我的Web应用程序显示信息,但是当我进行更改时,必须刷新页面以重新加载EF数据库上下文并从数据库加载更新的数据。

经过长时间的互联网搜索后,我了解到必须针对我的情况使用动态上下文,但是如何在EFCore中实现呢?我很困惑。是否有解决此问题的简单方法或学习动态上下文的良好资源。我将感谢您的帮助。

我的中心

public class StreamHub : Hub
    {
        private readonly LContext _context; // conn to Database

        public ChatHub(LContext _context)
        {
            this._context = _context;
        }

        public ChannelReader<string> DelayCounter(int delay) //that method I indicate in js-client

        {
            var channel = Channel.CreateUnbounded<string>();

            _ = WriteItems(channel.Writer, 200, delay);

            return channel.Reader;
        }

        private async Task WriteItems(ChannelWriter<string> writer, int count, int delay)
        {

            for (; ; ) //endless cycle
            {

                string LL = _context.Logs.OrderByDescending(s => s.OccurTime).FirstOrDefault().Flag; //that data which I want to streaming

                await writer.WriteAsync(LL);
                await Task.Delay(delay);
                await _context.Entry(LL).ReloadAsync();
                _context.Entry(LL).Reload();
            }

        }
    }

1 个答案:

答案 0 :(得分:0)

几件事。 DbContext不是线程安全的,因此它们只能在它们被访问的线程范围内。模块级变量将是一个禁忌。一旦解决了其映射的第一个一次性命中问题,DbContext旋转起来的成本也非常便宜。 (非常先针对该类型的DbContext进行查询)在需要时向上旋转,尤其是对于多线程或异步操作。

string LL = _context.Logs.OrderByDescending(s => s.OccurTime).FirstOrDefault().Flag; //that data which I want to streaming

这样可以更有效。您的代码有效地做到了:

SELECT TOP 1 * FROM Logs ORDER BY OccurTime DESC

更好的是:

string LL = context.Logs
    .OrderByDescending(s => s.OccurTime)
    .Select(s => s.Flag)
    .FirstOrDefault();

这等于:

SELECT TOP 1 Flag FROM Logs ORDER BY OccurTime DESC

区别在于,当我们只关心Flag属性时,第一个查询将返回日志的所有属性。

这些行看起来很好...

await writer.WriteAsync(LL);
await Task.Delay(delay);

这些没有任何意义。 “ flag”不是要重载的实体,它们是相同的方法,只是异步还是同步。

await _context.Entry(LL).ReloadAsync();
_context.Entry(LL).Reload();

我将更改代码以使其看起来像这样:

   private async Task WriteItems(ChannelWriter<string> writer, int count, int delay)
    {

        while (!_abort)
        {
            using(var context = new LContext())
            {
                string flag = _context.Logs
                    .OrderByDescending(s => s.OccurTime)
                    .Select(s => s.Flag)
                    .FirstOrDefault();
                await writer.WriteAsync(flag);
            }
            await Task.Delay(delay);
        }
    }

其中_abort是一个易失的布尔值,通过它我们可以让代码/用户使用信号通知后台任务应正常终止。

鉴于此代码将经常运行,因此我将考虑一种解决方案,该解决方案既可以写入日志数据库,又可以保留最近的条目在内存中的滚动缓存,以便像这样在每次访问数据库时都可以使用200ms增加了对于实时性可能并不重要的负载。