【问题标题】:Application-wide data in Blazor server appBlazor 服务器应用程序中的应用程序范围数据
【发布时间】:2021-01-12 22:47:52
【问题描述】:

我正在尝试了解在 Blazor 服务器应用程序中保留和访问缓存的全局应用程序参数的选项和最佳方法。

我最近才开始研究 Blazor,对这方面还很陌生,可能在这里思考完全错误的方向,因此非常感谢任何能指导我正确方向的输入。

基本上,我正在考虑一组不太可能经常更改的全局应用程序设置,因此没有必要在每个请求上读取 db。因此,我正在考虑类似于过去 .NET 世界中可能看起来像控制器中的函数的东西(为审查而简化):

 protected IGlobalSettings getGlobalSettings() 
 {
        globalSettings = HttpContext.Application["appSettings"] as IGlobalSettings;

        if(globalSettings == null)
        {
            using (globalConfigurator _gc = new globalConfigurator())
            {                
                globalSettings = _gc.configureSettings();
                HttpContext.Application["appSettings"] = globalSettings;
            }
        }

        return globalSettings;
}

我了解 .NET Core,我可以使用 DI 提供的 IMemoryCache 服务,可能类似于:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private IMemoryCache _cache;

    public HomeController(ILogger<HomeController> logger, IMemoryCache memoryCache)
    {
        _logger = logger;
        _cache = memoryCache;
    }

    public globalSettings getCachedData()
    {
        if (_cache.Get("appSetings") is not globalSettings _globalSettings)
        {
            using (globalConfigurator _gc = new globalConfigurator())
            {                
                _globalSettings = _gc.configureSettings();
                _cache.Set("appSetings", _globalSettings);
            }
        }
        
        return _globalSettings;
    }
}

这里的想法是 - globalSettings 对象可以被应用程序中的所有用户访问和使用(我现在不担心分布式缓存以及同步和保持 globalSettings 数据线程安全的问题)。对于 Blazor 组件(或 .NET Core razor 页面),让globalSettings 对象在可能需要访问该数据的所有页面中可用的最佳方法是什么?

理想情况下,我希望有一个服务,它提供globalSettings 对象并封装从缓存中提取或从数据库中提取,以防缓存中没有对象。这是一个很好的中间件候选人吗?在这种情况下,此中间件将需要访问 IMemoryCache 服务。

另一个我似乎很难解决的问题是:如何使用组件(页面)中的中间件来设置页面类实例的初始状态?像这样,DI 提供的服务将拉取页面的全局设置对象:

@page "/AppConfigSettings"

@inject IGlobalSettingsProvider settingsProvider 

<div class="row">
    <span><strong>Parameter #1</strong>@settings.parameterOne</span><br />
    <span><strong>Parameter #1</strong>@settings.parameterTwo</span><br />
    <span><strong>Parameter #1</strong>@settings.parameterThree</span><br />
</div>

@code {
    globalSettings settings = settingsProvider.globalSettings();
}

IGlobalSettingsProvider 服务将从IMemoryCache 拉取缓存的对象,如果对象不在缓存中,则进行构建。

我不确定我离这里有多远,再次感谢任何聪明的想法。

谢谢。

【问题讨论】:

  • Blazor 服务器端还是 Blazor WebAssembly?
  • Henk,我特别关注服务器端。对于这种情况 - 我不会担心浏览器端发生了什么。基本上,这个想法是能够处理一堆足够小且不经常更改的全局应用程序数据,因此 a) 保持在内存中的成本低廉,b) 能够节省前往 DB 的行程。考虑到这一点,我希望能够使用该数据来设置 Razor 组件实例对象的初始状态,因为它们被发送到浏览器。

标签: caching .net-core state blazor


【解决方案1】:

我想要一个服务,它提供 globalSettings 对象并封装从缓存中提取或从数据库中提取,以防缓存中没有对象。这是一个很好的中间件候选者吗?

服务是正确的方法,但中间件不适用。 Blazor 使用 SignalR 连接,而不是 Http 请求来显示其页面。

不过,您的缓存方法基本上还可以:

class GlobalSettingsProvider
{
    public GlobalSettingsProvider(IMemoryCache cache)
    {
       _cache = cache;
    }

    public GlobalSettings GetSettings()
    {
        return _cache.GetOrCreate("appSetings", entry => 
         {
             // configure timeout
             return new GlobalSettings();  // configure
         });
    }
}

在 Startup.ConfigureServices 中:

services.AddTransient<GlobalSettingsProvider>();

在您的网页中:

@inject GlobalSettingsProvider GlobalSettingsProvider

【讨论】:

  • 谢谢亨克。我怀疑“service.AddTransient();”在复数服务中可能缺少 S。 - 并且代码可能需要转到 Startup.ConfigureServices ,但这都是次要的,您的 cmets 真的很有帮助。我能够通过属性依赖注入来解决这个问题。谢谢!
  • 是的,主要是凭记忆。
猜你喜欢
  • 1970-01-01
  • 2021-08-12
  • 2023-01-19
  • 2020-09-18
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
相关资源
最近更新 更多