IDesignTimeDbContextFactory [TContext]违反了

时间:2018-05-18 15:36:39

标签: c# entity-framework-core identityserver4

我目前正在与this quickstart example合作,并且正在努力让它发挥作用。由于遇到了无穷无尽的异常,我已经放弃了开发数据库的第一个,而是希望从实体生成表,这不是我首选的工作方式。

我似乎没有这么做运气......

我目前正在反对这个例外:

  

PM> dotnet ef数据库更新CustomerDbContext   System.ArgumentException:GenericArguments [0],'IdentityServerWithAspIdAndEF.Migrations.CustomerDbContext','Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory 1[TContext]' violates the constraint of type 'TContext'. ---> System.TypeLoadException: GenericArguments[0], 'IdentityServerWithAspIdAndEF.Migrations.CustomerDbContext', on 'Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory 1 [TContext]'违反了类型参数'TContext'的约束。      在System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle句柄,IntPtr * pInst,Int32 numGenericArgs,ObjectHandleOnStack类型)      在System.RuntimeTypeHandle.Instantiate(Type [] inst)      在System.RuntimeType.MakeGenericType(Type [] instantiation)      ---内部异常堆栈跟踪结束---      at System.RuntimeType.ValidateGenericArguments(MemberInfo定义,RuntimeType [] genericArguments,Exception e)      在System.RuntimeType.MakeGenericType(Type [] instantiation)      在Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextFactory(类型contextType)      在Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextTypes()      在Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextType(String name)      在Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)      在Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration,String contextType)      在Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase。<> c__DisplayClass0_1。< .ctor> b__0()      在Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)   'Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory`1 [TContext]'上的GenericArguments [0],'IdentityServerWithAspIdAndEF.Migrations.CustomerDbContext'违反了'TContext'类型的约束。

对我来说,就像“错误,出现错误”一样具有描述性......我已经采取了原始的快速入门并进行了以下修改。

Startup.ConfigureServices现在是:

public void ConfigureServices(IServiceCollection services)
{
    string connectionString = Configuration.GetConnectionString("DefaultConnection");
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    services.AddDbContext<CustomerDbContext>(options =>
        options.UseSqlServer(connectionString)
    );

    services.AddIdentity<User, Role>()
        .AddUserStore<CustomerUserStore>()
        .AddUserManager<CustomerManager>()
        .AddRoleStore<CustomerRoleStore>()
        .AddRoleManager<RoleManager>()
        .AddSignInManager<CustomerSignInManager>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    services.Configure<IISOptions>(iis =>
    {
        iis.AuthenticationDisplayName = "Windows";
        iis.AutomaticAuthentication = false;
    });

    var builder = services.AddIdentityServer(options =>
        {
            options.Events.RaiseErrorEvents = true;
            options.Events.RaiseInformationEvents = true;
            options.Events.RaiseFailureEvents = true;
            options.Events.RaiseSuccessEvents = true;
        })
        .AddAspNetIdentity<User>()
        // this adds the config data from DB (clients, resources)
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = b =>
                b.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
        })
        // this adds the operational data from DB (codes, tokens, consents)
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = b =>
                b.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));

            // this enables automatic token cleanup. this is optional.
            options.EnableTokenCleanup = true;
            // options.TokenCleanupInterval = 15; // frequency in seconds to cleanup stale grants. 15 is useful during debugging
        });

    if (Environment.IsDevelopment())
    {
        builder.AddDeveloperSigningCredential();
    }
    else
    {
        throw new Exception("need to configure key material");
    }

    services.AddAuthentication();
}

ApplicationDbContext已重命名为CustomerDbContext,而OnModelCreating现已改名为:

protected override void OnModelCreating(ModelBuilder ModelBuilder)
{
    base.OnModelCreating(ModelBuilder);

    ModelBuilder.Entity<User>(E =>
    {
        E.ToTable("Users");
    });

    ModelBuilder.Entity<Role>(E =>
    {
        E.ToTable("Roles");
    });

    ModelBuilder.Entity<RoleClaim>(E =>
    {
        E.ToTable("RoleClaims");
    });

    ModelBuilder.Entity<UserClaim>(E =>
    {
        E.ToTable("UserClaims");
    });

    ModelBuilder.Entity<UserRole>(E =>
    {
        E.ToTable("UserRoles");
    });

    // "Microsoft.AspNetCore.Identity.IdentityUserLogin<string>"
    ModelBuilder.Entity<Login>(E =>
    {
        E.Property(P => P.LoginId)
            .IsRequired()
            .HasColumnName("LoginId")
            .ValueGeneratedOnAdd();

        E.HasIndex(P => P.LoginProvider)
            .HasName("IX_Logins_LoginProvider");

        E.HasIndex(P => P.ProviderKey)
            .HasName("IX_Logins_ProviderKey");

        E.HasIndex(P => P.UserId)
            .HasName("IX_Logins_AccountId");

        E.ToTable("Logins");
    });

    // "Microsoft.AspNetCore.Identity.IdentityUserToken<string>"
    ModelBuilder.Entity<Token>(E =>
    {
        E.Property(P => P.TokenId)
            .IsRequired()
            .HasColumnName("TokenId")
            .ValueGeneratedOnAdd();

        E.ToTable("Tokens");
    });
}

最后,我把一堆东西混在一起让模特工作;所以ApplicationUser文件现在包含:

public class User : IdentityUser<int>
{
}

public class Role : IdentityRole<int>
{
}

public class RoleClaim : IdentityRoleClaim<int>
{
}

public class UserClaim : IdentityUserClaim<int>
{
}

public class Login : IdentityUserLogin<int>
{
    public int LoginId { get; set; }
}

public class UserRole : IdentityUserRole<int>
{
}

public class Token : IdentityUserToken<int>
{
    public int TokenId { get; set; }
}
public class CustomerManager : UserManager<User>
{
    /// <summary>
    /// Constructs a new instance of <see cref="T:Microsoft.AspNetCore.Identity.UserManager`1" />.
    /// </summary>
    /// <param name="Store">The persistence store the manager will operate over.</param>
    /// <param name="OptionsAccessor">The accessor used to access the <see cref="T:Microsoft.AspNetCore.Identity.IdentityOptions" />.</param>
    /// <param name="PasswordHasher">The password hashing implementation to use when saving passwords.</param>
    /// <param name="UserValidators">A collection of <see cref="T:Microsoft.AspNetCore.Identity.IUserValidator`1" /> to validate users against.</param>
    /// <param name="PasswordValidators">A collection of <see cref="T:Microsoft.AspNetCore.Identity.IPasswordValidator`1" /> to validate passwords against.</param>
    /// <param name="KeyNormaliser">The <see cref="T:Microsoft.AspNetCore.Identity.ILookupNormalizer" /> to use when generating index keys for users.</param>
    /// <param name="Errors">The <see cref="T:Microsoft.AspNetCore.Identity.IdentityErrorDescriber" /> used to provider error messages.</param>
    /// <param name="Services">The <see cref="T:System.IServiceProvider" /> used to resolve services.</param>
    /// <param name="Logger">The logger used to log messages, warnings and errors.</param>
    public CustomerManager(
        IUserStore<User> Store,
        IOptions<IdentityOptions> OptionsAccessor,
        IPasswordHasher<User> PasswordHasher,
        IEnumerable<IUserValidator<User>> UserValidators,
        IEnumerable<IPasswordValidator<User>> PasswordValidators,
        ILookupNormalizer KeyNormaliser,
        IdentityErrorDescriber Errors,
        IServiceProvider Services,
        ILogger<UserManager<User>> Logger
    ) : base(
        Store,
        OptionsAccessor,
        PasswordHasher,
        UserValidators,
        PasswordValidators,
        KeyNormaliser,
        Errors,
        Services,
        Logger
    )
    { }
}

public class RoleManager : RoleManager<Role>
{
    /// <summary>
    /// Constructs a new instance of <see cref="T:Microsoft.AspNetCore.Identity.RoleManager`1" />.
    /// </summary>
    /// <param name="Store">The persistence store the manager will operate over.</param>
    /// <param name="RoleValidators">A collection of validators for roles.</param>
    /// <param name="KeyNormalizer">The normalizer to use when normalizing role names to keys.</param>
    /// <param name="Errors">The <see cref="T:Microsoft.AspNetCore.Identity.IdentityErrorDescriber" /> used to provider error messages.</param>
    /// <param name="Logger">The logger used to log messages, warnings and errors.</param>
    public RoleManager(
        IRoleStore<Role> Store,
        IEnumerable<IRoleValidator<Role>> RoleValidators,
        ILookupNormalizer KeyNormalizer,
        IdentityErrorDescriber Errors,
        ILogger<RoleManager<Role>> Logger
    ) : base(
        Store,
        RoleValidators,
        KeyNormalizer,
        Errors,
        Logger
    )
    { }
}

public class CustomerSignInManager : SignInManager<User>
{
    /// <summary>
    /// Creates a new instance of <see cref="T:Microsoft.AspNetCore.Identity.SignInManager`1" />.
    /// </summary>
    /// <param name="UserManager">An instance of <see cref="P:Microsoft.AspNetCore.Identity.SignInManager`1.UserManager" /> used to retrieve users from and persist users.</param>
    /// <param name="ContextAccessor">The accessor used to access the <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param>
    /// <param name="ClaimsFactory">The factory to use to create claims principals for a user.</param>
    /// <param name="OptionsAccessor">The accessor used to access the <see cref="T:Microsoft.AspNetCore.Identity.IdentityOptions" />.</param>
    /// <param name="Logger">The logger used to log messages, warnings and errors.</param>
    /// <param name="Schemes">The logger used to log messages, warnings and errors.</param>
    public CustomerSignInManager(
        UserManager<User> UserManager,
        IHttpContextAccessor ContextAccessor,
        IUserClaimsPrincipalFactory<User> ClaimsFactory,
        IOptions<IdentityOptions> OptionsAccessor,
        ILogger<SignInManager<User>> Logger,
        IAuthenticationSchemeProvider Schemes
    ) : base(
        UserManager,
        ContextAccessor,
        ClaimsFactory,
        OptionsAccessor,
        Logger,
        Schemes
    )
    { }
}

public class CustomerUserStore : UserStore<User, Role, CustomerDbContext, int, UserClaim, UserRole, Login, Token, RoleClaim>
{
    public CustomerUserStore(CustomerDbContext Context) : base(Context)
    {

    }
}

public class CustomerRoleStore : RoleStore<Role, CustomerDbContext, int, UserRole, RoleClaim>
{
    /// <summary>
    /// Constructs a new instance of <see cref="T:Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore`5" />.
    /// </summary>
    /// <param name="context">The <see cref="T:Microsoft.EntityFrameworkCore.DbContext" />.</param>
    /// <param name="describer">The <see cref="T:Microsoft.AspNetCore.Identity.IdentityErrorDescriber" />.</param>
    public CustomerRoleStore(
        CustomerDbContext context,
        IdentityErrorDescriber describer = null
    ) : base(
        context,
        describer
    )
    { }

    /// <summary>Creates a entity representing a role claim.</summary>
    /// <param name="role">The associated role.</param>
    /// <param name="claim">The associated claim.</param>
    /// <returns>The role claim entity.</returns>
    protected override RoleClaim CreateRoleClaim(Role role, Claim claim)
    {
        return new RoleClaim
        {
            RoleId = role.Id,
            ClaimType = claim.Type,
            ClaimValue = claim.Value
        };
    }
}

我已导航到src/IdentityServerWithAspIdAndEF文件夹,将“启动项目”设置为IdentityServerWithAspIdAndEF,然后运行以下命令尝试生成表格:

PM> Add-Migration CustomerDbContext -Context CustomerDbContext 然后 PM> dotnet ef database update CustomerDbContext

第一个生成Migrations文件夹和预期的* .cs文件;第二个产生了在这篇文章顶部看到的错误。

有人可以告知可能产生此错误的内容吗?

4 个答案:

答案 0 :(得分:0)

最常见的解决方法是删除您的迁移文件夹中具有相同名称的所有迁移,但是,如果这样做不起作用,建议您删除所有迁移,如果创建了数据库,则删除数据库。

然后,您应该能够运行Add-Migration CustomerDbContext -Context CustomerDbContextdotnet ef database update而不会出错。

答案 1 :(得分:0)

在脚本中重命名迁移后,您应该能够运行它。

function GetLoginModalCB(strModalHTML) { $('#modalDiv').html(strModalHTML); }

重命名迁移后它对我有用。

答案 2 :(得分:0)

由于创建DBContext和初始迁移之后,我遇到了相同的错误,因此尝试更改DbContext名称并更新数据库。我在DbContext中回滚了名称,一切都按预期开始工作。

答案 3 :(得分:0)

我有同样的问题。 删除所有迁移和文件夹“迁移” 后,它也能正常工作。