C# 在Asp.net core中设置IdentityRole种子时出错
我无法将数据植入标识角色表。我总是犯错误 System.NullReferenceException:'对象引用未设置为 对象的实例。” 4.此角色管理器为空 我不知道为什么会发生这种情况,为什么没有将数据植入表中。我该如何解决这个问题? 下面是我的代码C# 在Asp.net core中设置IdentityRole种子时出错,c#,entity-framework,asp.net-core,asp.net-identity,C#,Entity Framework,Asp.net Core,Asp.net Identity,我无法将数据植入标识角色表。我总是犯错误 System.NullReferenceException:'对象引用未设置为 对象的实例。” 4.此角色管理器为空 我不知道为什么会发生这种情况,为什么没有将数据植入表中。我该如何解决这个问题? 下面是我的代码 public class UserRoleSeed { private readonly RoleManager<IdentityRole> _roleManager; private string[] _roleA
public class UserRoleSeed
{
private readonly RoleManager<IdentityRole> _roleManager;
private string[] _roleArray = { "Admin, TerminalManager, Dispatcher, Driver, Mechanic, Recruiter, MechanicManger" };
public UserRoleSeed(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
public async void Seed()
{
foreach (string index in _roleArray)
{
if ((await _roleManager.FindByNameAsync(index)) == null)
{
await _roleManager.CreateAsync(new IdentityRole { Name = index });
}
}
}
}
public类UserRoleSeed
{
专用只读角色管理器(RoleManager);
私有字符串[]_rolarray={“管理员、终端管理员、调度员、驾驶员、机械师、招聘人员、机械愤怒”};
公共用户RoleSeed(RoleManager RoleManager)
{
_roleManager=roleManager;
}
公共异步void Seed()
{
foreach(RolArray中的字符串索引)
{
if((wait _roleManager.findbynamesync(index))==null)
{
wait _rolemager.CreateAsync(新的IdentityRole{Name=index});
}
}
}
}
为我的Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TransportDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
services.AddIdentity<ApplicationUser, IdentityRole<int>>()
.AddEntityFrameworkStores<TransportDbContext>()
.AddDefaultTokenProviders();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
//app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(
routes =>
{
routes.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}");
});
}
// seeds data into the identity role table
new UserRoleSeed(app.ApplicationServices.GetService<RoleManager<IdentityRole>>()).Seed();
}
}
}
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”));
services.AddMvc();
服务.额外性()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
}
公共void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
//app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(
路线=>
{
MapRoute(“默认值”,“{controller=Home}/{action=Index}/{id?}”);
});
}
//将数据种子放入标识角色表
新的UserRoleSeed(app.ApplicationServices.GetService()).Seed();
}
}
}
您正在使用异步方法为您的角色设定种子,但您并没有等待它。这意味着您的代码将继续前进,当分支超出范围时,最终将在异步方法中使用您所依赖的变量。因此,NullReferenceException
s
此外,像RoleManager
这样的服务是“范围”服务,这意味着它们只能从特定的活动范围中检索。在实际请求中,将为请求创建一个作用域,允许将这些服务注入到请求管道中的任何内容中。但是,这里没有活动作用域,因此必须创建一个
您应该将此代码移出程序
类,而不是尝试将其作为配置
方法的一部分进行播种。以下代码解决了上述两个问题:
public class Program
{
public static void Main(string[] args) =>
MainAsync(args).GetAwaiter().GetResult();
public static async Task MainAsync(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
await new UserRoleSeed(scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>()).Seed();
}
await host.RunAsync();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
无需从Main
代理到mainsync
,但在后台,编译器只需为您设置相同的结构
这是使代码正常工作的最短路径,但仍有一些小问题。首先,应该避免使用异步void
,这是一种反模式。您实际上是在吞咽异步输出,包括可能抛出的任何异常。当您不关心实际返回时,实际上应该始终使用async Task
作为返回。需要使用async void
的个人知道有几种情况是合适的。换句话说,如果您不知道什么时候应该使用async-void
,那么就不应该使用async-void
另外,虽然从技术上讲,新建一个类并将依赖项传递给构造函数并没有什么错,但在这种情况下,更合适的做法是使类成为静态的,并将所需的依赖项传递给seed方法:
await UserRoleSeed.Seed(roleManager);
最后,虽然不是很重要,但按照惯例,命名异步方法时要使用
async
后缀。这清楚地表明该方法是异步的,并防止意外地不等待该方法,因为它不明显需要等待(这里可能就是这种情况)。简言之,将名称从Seed
更改为SeedAsync
,因为它可以异步工作。您正在使用异步方法为角色设定种子,但您没有等待它。这意味着您的代码将继续前进,当分支超出范围时,最终将在异步方法中使用您所依赖的变量。因此,NullReferenceException
s
此外,像RoleManager
这样的服务是“范围”服务,这意味着它们只能从特定的活动范围中检索。在实际请求中,将为请求创建一个作用域,允许将这些服务注入到请求管道中的任何内容中。但是,这里没有活动作用域,因此必须创建一个
您应该将此代码移出程序
类,而不是尝试将其作为配置
方法的一部分进行播种。以下代码解决了上述两个问题:
public class Program
{
public static void Main(string[] args) =>
MainAsync(args).GetAwaiter().GetResult();
public static async Task MainAsync(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
await new UserRoleSeed(scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>()).Seed();
}
await host.RunAsync();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
无需从Main
代理到mainsync
,但在后台,编译器只需为您设置相同的结构
这是使代码正常工作的最短路径,但仍有一些小问题。首先,应该避免使用异步void
,这是一种反模式。您实际上是在吞咽异步输出,包括可能抛出的任何异常。当您不关心实际返回时,实际上应该始终使用async Task
作为返回。需要使用async void
的个人知道有几种情况是合适的。换句话说,如果您不知道什么时候应该使用async void
,那么就不应该使用 public class DbInitializer
{
private static readonly string[] _roleArray = { "Admin", "Terminal Manager", "Dispatcher", "Driver", "Mechanic", "Recruiter", "Mechanic Manger" };
public static async Task InitializeAync (TransportDbContext context, IServiceProvider serviceProvider)
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<Role>>();
foreach (string index in _roleArray)
{
if ((await roleManager.FindByNameAsync(index)) == null)
{
await roleManager.CreateAsync(new Role { Name = index });
}
}
}
}}
public class Program
{
public static void Main(string[] args) =>
MainAsync(args).GetAwaiter().GetResult();
public static async Task MainAsync(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var context = services.GetRequiredService<TransportDbContext>();
await DbInitializer.InitializeAync(context, services);
}
await host.RunAsync();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
} }