我正在使用Blazor Server,但希望页面上的业务逻辑尽可能少,特别是可以 Select 创建REST端点,这些端点可以处理与我的Blazor Server应用程序相同的用例,因此我的UI中的加载和保存方法看起来非常类似:
private async Task HandleValidSubmit()
{
if (_myDto != default)
{
_myDto.Id = await MyEntityService.Save(_myDto);
}
}
在MyEntityService
中(它位于一个单独的类库中,因此我可以很容易地在future 的REST API中使用它),然后我通过DI注入MyContext
:
public class MyEntityService : IMyEntityService
{
private readonly ILogger<MyEntityService> _logger;
private readonly IMyContext _context;
public MyEntityService(ILogger<MyEntityService> logger, IMyContext context)
{
_logger = logger;
_context = context;
}
public async Task<int> Save(DtoMyEntity dtoToSave)
{
_logger.LogTrace("{method}({dtoToSave})", nameof(Save), dtoToSave);
//Some magic to convert my DTO to an EF Core entity
await _context.SaveChangesAsync().ConfigureAwait(false);
return entity.Id;
}
}
以下是我在数据库上下文中的DI配置:
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDatabase(this IServiceCollection services)
=> services
.AddDbContext<IMyContext, MyContext>((provider, options) =>
{
options.UseNpgsql(provider.GetRequiredService<IDbConnectionStringHelper>()
.GetDbConnectionString("ServiceDatabase"));
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (environment == "Development")
{
options.EnableSensitiveDataLogging();
}
options.EnableDetailedErrors();
}, ServiceLifetime.Transient, ServiceLifetime.Transient)
.AddTransient<IDbConnectionStringHelper, DbConnectionStringHelper>()
;
}
现在,当我在没有重新加载页面的情况下单击Save
两次/转到另一个页面并返回时,我收到以下错误:
The instance of entity type 'MyEntity' cannot be tracked because another instance with the key value '{Id: 1}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
我如何解决此问题?我知道我应该使用IDbContextFactory
作为解释on the Microsoft docs here,但这似乎是非常Blazor服务器特定的.我还希望在REST API中使用我的后端类库,在REST API中,仅使用生存期为Transient
的上下文是绝对可以的.