如何在 .NET Core 2.0 中播种角色?

How to Seed Roles in .NET Core 2.0?

目前我正在尝试使用内置于 .NET Core 2.0 的 mvc-framework RoleManager<Identity> 配置角色。

但是我收到以下错误:

System.ObjectDisposedException
HResult=0x80131622
Message=Cannot access a disposed object. A common cause of this error is 
disposing a context 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, or wrapping the 
context in a using statement. If you are using dependency injection, you 
should let the dependency injection container take care of disposing context 
instances. The error occured in line 20 of UserRoleSeed-class.

这是因为 Seed() 方法的异步特性吗?

我的Program.cs:

public class Program
{
    public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var serviceProvider = scope.ServiceProvider;
            try
            {
                var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

                new UserRoleSeed(roleManager).Seed();
            }
            catch
            {
                throw new Exception();
            }
        }

        host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

我的UserRoleSeed.cs:

public class UserRoleSeed
{
    private readonly RoleManager<IdentityRole> _roleManager;

    public UserRoleSeed(RoleManager<IdentityRole> roleManager)
    {
        _roleManager = roleManager;
    }

    public async void Seed()
    {
        if ((await _roleManager.FindByNameAsync("Berijder")) == null)
        {
            await _roleManager.CreateAsync(new IdentityRole {Name = 
        "Berijder"});
        }
    }
}

这应该在我的上下文 imo 的 dbo.AspNetRoles table 中创建一个新条目,但它没有。问题可能有点小,这是我第一次尝试在 Mvc 框架中使用角色。

我一开始尝试使用Startup.cs文件,在这个文件的Configure()方法中调用Seed()方法,没用(可能因为这是CORE 2.0和不是 1.0).

async void 用作即发即弃方法。代码将继续 运行 并在 async void 完成之前处理所有对象。 另一种处理方法:

将其设为异步 Task 并调用 Wait();

public async Task SeedAsync()
{
    ...
}

这样称呼它:

// Calling Wait in EFCore is not so much of a problem, since there is not
// really a main blocking thread like UI program's have in .NET framework.
new UserRoleSeed(roleManager).SeedAsync().Wait();

另一个解决方案是使用任务 运行ner:

public static void Main(string[] args)
{
    var host = BuildWebHost(args);
    Task.Run(() => InitializeAsync(host));
    host.Run();
}

private static async Task InitializeAsync(IWebHost host)
{
    using (var scope = host.Services.CreateScope())
    {
        var serviceProvider = scope.ServiceProvider;
        try
        {
            var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

            await new UserRoleSeed(roleManager).SeedAsync();
        }
        catch
        {
            // TODO: log the exception
            throw;
        }
    }
}

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build();