Blazor Server 组件之间的一致数据库上下文
Blazor Server consistent database context between components
我想问一下,在组件之间使用数据库上下文的最佳实践是什么?
Blazor 服务器、.Net 5、EF 核心 5.0.8
情况简述:
组件a,表头
组件 b,主要
DbContext 注册为 Transient,Header 和 Main 都有自己的上下文。
但是在例如:更改 Main 中的数据后,它不适用于 Header,因此数据变得不一致。
想法:
1,删除 DbContext 注册并为每个数据库调用手动创建一个新的
2,保持当前架构,但添加一个额外的调用来刷新数据(在需要的地方)
3,将 DbContext 注册为 Scoped 并围绕它构建某种队列服务以逐个处理查询(避免并发调用)并通过 EventAggregator 消息 return 结果。
你怎么看,你是怎么处理这种情况的?
首先,永远不要将 dbcontext 注册为瞬态。它会导致内存和连接泄漏,因为谁来处理 dbcontext?如果它被注入,那么预计注入器将负责处理它 - 在这种情况下是 ServiceProvider,但服务提供者不会处理瞬态服务。
您应该使用 IDbContextFactory<TContext>
class 并在需要时创建新实例。请记住,DbContext 是短暂的
根据@Liero 的回答,我最初还使用 IDbContextFactory 在每次服务调用数据库时创建一个新的上下文实例 - 但是对于我的应用程序,我需要跨多个组件进行更改跟踪,我做到了不想打破工作单元模式,因为这会导致一些数据库不一致的问题。
正如您在步骤 (3) 中提到的那样 - 我将 DbContext 保持在范围内(AFAIK 这是默认设置),然后我使用 semaphore 来防止线程问题:
@code {
static Semaphore semaphore;
//code ommitted for brevity
protected override async Task OnInitializedAsync()
{
try
{
//First open global semaphore
semaphore = Semaphore.OpenExisting("GlobalSemaphore");
while (!semaphore.WaitOne(TimeSpan.FromTicks(1)))
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
//If while loop is exited or skipped, previous service calls are completed.
ApplicationUsers = await ApplicationUserService.Get();
}
finally
{
try
{
semaphore.Release();
}
catch (Exception ex)
{
Console.WriteLine("ex.Message");
}
}
}
这对于我需要跨组件保留更改跟踪的特定用例非常有效。 Here's my full answer from another related question.
我想问一下,在组件之间使用数据库上下文的最佳实践是什么? Blazor 服务器、.Net 5、EF 核心 5.0.8
情况简述:
组件a,表头
组件 b,主要
DbContext 注册为 Transient,Header 和 Main 都有自己的上下文。
但是在例如:更改 Main 中的数据后,它不适用于 Header,因此数据变得不一致。
想法:
1,删除 DbContext 注册并为每个数据库调用手动创建一个新的
2,保持当前架构,但添加一个额外的调用来刷新数据(在需要的地方)
3,将 DbContext 注册为 Scoped 并围绕它构建某种队列服务以逐个处理查询(避免并发调用)并通过 EventAggregator 消息 return 结果。
你怎么看,你是怎么处理这种情况的?
首先,永远不要将 dbcontext 注册为瞬态。它会导致内存和连接泄漏,因为谁来处理 dbcontext?如果它被注入,那么预计注入器将负责处理它 - 在这种情况下是 ServiceProvider,但服务提供者不会处理瞬态服务。
您应该使用 IDbContextFactory<TContext>
class 并在需要时创建新实例。请记住,DbContext 是短暂的
根据@Liero 的回答,我最初还使用 IDbContextFactory 在每次服务调用数据库时创建一个新的上下文实例 - 但是对于我的应用程序,我需要跨多个组件进行更改跟踪,我做到了不想打破工作单元模式,因为这会导致一些数据库不一致的问题。
正如您在步骤 (3) 中提到的那样 - 我将 DbContext 保持在范围内(AFAIK 这是默认设置),然后我使用 semaphore 来防止线程问题:
@code {
static Semaphore semaphore;
//code ommitted for brevity
protected override async Task OnInitializedAsync()
{
try
{
//First open global semaphore
semaphore = Semaphore.OpenExisting("GlobalSemaphore");
while (!semaphore.WaitOne(TimeSpan.FromTicks(1)))
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
//If while loop is exited or skipped, previous service calls are completed.
ApplicationUsers = await ApplicationUserService.Get();
}
finally
{
try
{
semaphore.Release();
}
catch (Exception ex)
{
Console.WriteLine("ex.Message");
}
}
}
这对于我需要跨组件保留更改跟踪的特定用例非常有效。 Here's my full answer from another related question.