【问题标题】:How to Seed Roles in .NET Core 2.0?如何在 .NET Core 2.0 中播种角色?
【发布时间】:2019-01-22 21:15:40
【问题描述】:

目前我正在尝试使用 RoleManager<Identity> 配置角色,内置于 .NET Core 2.0,mvc 框架中。

但是我收到以下错误:

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"});
        }
    }
}

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

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

【问题讨论】:

  • 您正在调用异步 void。不要那样做。而是让它同步或 Task 并调用 ...Seed().Wait(); 你应该没问题,像这样调用 Wait ,因为这是 EF Core 而你没有做任何 UI 调度程序的东西。
  • 非常感谢,解决了我的问题!发表答案,我会接受!

标签: c# asp.net-core .net-core asp.net-core-mvc .net-core-2.0


【解决方案1】:

async void 用作即发即弃的方法。在异步 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();

另一种解决方案是使用任务运行器:

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();

【讨论】:

  • 为什么我应该使用 Task-runner 而不是上面更简单的方法?
  • @ramonabacherli 做对你有用的事。我通常会创建一个类似后者的异步初始化方法,以便能够轻松添加更多异步调用。
猜你喜欢
  • 1970-01-01
  • 2018-09-13
  • 2020-09-13
  • 1970-01-01
  • 2018-07-03
  • 2019-08-05
  • 2018-09-05
  • 2018-02-05
  • 1970-01-01
相关资源
最近更新 更多