如何在 ConfigureServices 中创建依赖于数据库上下文的实例
How create an instance which depends on a database context in ConfigureServices
你好 Whosebug 的人,
我需要一个 class 的实例,它依赖于数据库上下文服务,例如
services.AddScoped<IAccountCreationService, AccountCreationService>();
var _accountCreationService = services.BuildServiceProvider().GetService<IAccountCreationService>();
services
.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options => {
options.Events = new Authentication.CustomCookieAuthenticationEvents {
accountCreationService = _accountCreationService,
};
})
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Zukte.Database;
using Zukte.Message.ApplicationUser;
namespace Zukte.Utilities.Account {
/// <inheritdoc/>
public class AccountCreationService : IAccountCreationService {
private readonly ApplicationDbContext databaseService;
public AccountCreationService(ApplicationDbContext databaseService) {
this.databaseService = databaseService;
}
public async Task<ApplicationUser> PostApplicationUser(ApplicationUser applicationUser) {
}
}
}
当使用BuildServiceProvider()
方法时我运行进入以下错误:
The instance of entity type 'ApplicationUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
因为“注入”到 AccountCreationService 中的数据库服务没有像往常一样处理掉。此外,如果我使用这种替代方法:
IAccountCreationService? accountCreator = null;
services.AddScoped<IAccountCreationService>(serviceProvider => {
var databaseService = serviceProvider.GetService<ApplicationDbContext>() ??
throw new System.ArgumentNullException(nameof(ApplicationDbContext));
accountCreator = new AccountCreationService(databaseService);
return accountCreator;
});
然后 accountCreationService
将为 null 或我 运行 进入以下错误:
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.
因为“注入”到 AccountCreationService 中的数据库服务被处理掉了。
如何变通或解决这个问题?我希望能够在用户登录后将帐户持久保存到数据库中。
感谢 devNull's 评论,我得以解决这个问题。
使用这种方法,您可以在 AddCookie 方法中使用 DI:
).AddCookie(options => {
options.EventsType = typeof(CustomCookieAuthenticationEvents);
你好 Whosebug 的人,
我需要一个 class 的实例,它依赖于数据库上下文服务,例如
services.AddScoped<IAccountCreationService, AccountCreationService>();
var _accountCreationService = services.BuildServiceProvider().GetService<IAccountCreationService>();
services
.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options => {
options.Events = new Authentication.CustomCookieAuthenticationEvents {
accountCreationService = _accountCreationService,
};
})
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Zukte.Database;
using Zukte.Message.ApplicationUser;
namespace Zukte.Utilities.Account {
/// <inheritdoc/>
public class AccountCreationService : IAccountCreationService {
private readonly ApplicationDbContext databaseService;
public AccountCreationService(ApplicationDbContext databaseService) {
this.databaseService = databaseService;
}
public async Task<ApplicationUser> PostApplicationUser(ApplicationUser applicationUser) {
}
}
}
当使用BuildServiceProvider()
方法时我运行进入以下错误:
The instance of entity type 'ApplicationUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
因为“注入”到 AccountCreationService 中的数据库服务没有像往常一样处理掉。此外,如果我使用这种替代方法:
IAccountCreationService? accountCreator = null;
services.AddScoped<IAccountCreationService>(serviceProvider => {
var databaseService = serviceProvider.GetService<ApplicationDbContext>() ??
throw new System.ArgumentNullException(nameof(ApplicationDbContext));
accountCreator = new AccountCreationService(databaseService);
return accountCreator;
});
然后 accountCreationService
将为 null 或我 运行 进入以下错误:
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.
因为“注入”到 AccountCreationService 中的数据库服务被处理掉了。
如何变通或解决这个问题?我希望能够在用户登录后将帐户持久保存到数据库中。
感谢 devNull's 评论,我得以解决这个问题。
使用这种方法,您可以在 AddCookie 方法中使用 DI:
).AddCookie(options => {
options.EventsType = typeof(CustomCookieAuthenticationEvents);