【发布时间】:2022-10-24 23:18:36
【问题描述】:
我有一个 Blazor 服务器应用程序。此应用程序连接到 SQL DB,目前相对复杂。由于主要关注可用性,我们在直接访问数据库时遇到了一些问题(组件未正确更新等)。
因此,我正在尝试创建一个StateService,它基本上充当某种“缓存”。数据存储在其中,组件可以访问它,无需任何加载时间。在我的研究过程中,我有一些问题,文档无法回答我。
问题
应该有可能所有组件始终具有数据的最新状态。这意味着需要自动通知客户端任何更改并自动刷新其状态。还应该有能力为大约 1.000 个并发用户提供服务,而无需升级到高端服务器(我知道,这很模糊)。
可能的解决方案
单身状态
我基本上有一个服务,它将数据作为属性保存在其中,并有一个OnChange-event。每当设置任何数据属性时,都会触发事件。然后组件使用此服务来显示数据。当我将数据添加到数据库时,数据将自动加载回状态。我将此服务添加为单例,因此在服务器运行时只有一个对象。
public class SharedStateService
{
public event Action OnChange;
private ICollection<MyData>? myData;
public ICollection<MyData>? MyData
{
get => this.myData;
set
{
this.myData= value;
this.OnChange?.Invoke();
}
}
}
public class MyDataService
{
private readonly SharedStateService sharedStateService;
private readonly TestDbContext context;
public MyDataService(TestDbContext context, SharedStateService sharedService)
{
this.context = context;
this.sharedStateService = sharedService;
}
public async Task<bool> DeleteData(MyData data)
{
try
{
this.context.Set<MyData>().Remove(data);
await this.context.SaveChangesAsync();
}
catch (Exception)
{
return false;
}
await this.ReloadData();
return true;
}
public async Task ReloadData()
{
this.sharedStateService.MyData =
await this.context.Set<MyData>().ToListAsync();
}
}
在我看来,现在可以订阅OnChange 事件并自由使用MyData 属性。
<table class="table">
<thead>
<tr>
<!-- ... -->
</tr>
</thead>
<tbody>
@foreach (var data in SharedStateService.MyData)
{
<tr>
<!-- ... -->
</tr>
}
</tbody>
</table>
@code {
public void Dispose()
{
SharedStateService.OnChange -= Refresh;
}
protected override void OnInitialized()
{
SharedStateService.OnChange += Refresh;
}
private async void Refresh()
{
await InvokeAsync(this.StateHasChanged);
}
}
我在这种情况下看到的问题是整个数据不断地存储在服务器上。会不会有什么问题?我是不是想太多了?这种方法可能存在哪些风险?
单例事件
它类似于单例状态,但我不会将数据存储在任何地方。而不是状态,我有一个服务,它只提供一个可以订阅的事件。该服务再次作为单例添加。
public class RefreshService
{
public event Action OnChange;
public void Refresh()
{
OnChange?.Invoke();
}
}
然后将该服务注入数据提供者并在发生更改时调用。
我通过一种新方法扩展了MyDataService。
public async Task<ICollection<MyData>> GetAll()
{
return await this.context.Set<MyData>().ToListAsync();
}
之后,在我看来,我添加一个属性并调整Refresh 方法,以将数据加载到此本地属性中。
private async void Refresh()
{
this.MyData= await MyDataService.GetAll();
await InvokeAsync(this.StateHasChanged);
}
这种方法与第一种方法非常相似,但我不需要不断地存储数据。这种方法对服务器来说更容易处理吗?由于数据是冗余存储的,这会导致显示错误的数据吗?
我知道这是一篇长篇文章,但也许有人知道哪种方法通常比另一种更可取。
【问题讨论】:
标签: asp.net dependency-injection blazor singleton blazor-server-side