我正在从事.NetCore MVC项目,在该项目中,我不得不对现有数据库进行逆向工程,并且真是一场噩梦,使ASPIdentity发挥出色。
我不得不在创建的Context类中手动添加我的Identity DbSet,但其中不包括我希望会发生的Identity表。我设法为所需的ASPIdentity属性(角色,声明)创建了Migrations,并测试了项目的Registration / Login / Manage方面。单击“管理”区域中的“两因素身份验证”选项卡时,出现以下错误:
ArgumentException: Entity type 'IdentityUserToken<string>' is defined with a single key property, but 3 values were passed to the 'DbSet.Find' method.
Microsoft.EntityFrameworkCore.Internal.EntityFinder<TEntity>.FindTracked(object[] keyValues, out IReadOnlyList<IProperty> keyProperties)
Stack Query Cookies Headers
ArgumentException: Entity type 'IdentityUserToken<string>' is defined with a single key property, but 3 values were passed to the 'DbSet.Find' method.
Microsoft.EntityFrameworkCore.Internal.EntityFinder<TEntity>.FindTracked(object[] keyValues, out IReadOnlyList<IProperty> keyProperties)
Microsoft.EntityFrameworkCore.Internal.EntityFinder<TEntity>.FindAsync(object[] keyValues, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.FindAsync(object[] keyValues, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore<TUser, TRole, TContext, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim>.FindTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken>.GetTokenAsync(TUser user, string loginProvider, string name, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal.TwoFactorAuthenticationModel<TUser>.OnGetAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod.Convert<T>(object taskAsObject)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod.Execute(object receiver, object[] arguments)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeHandlerMethodAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeNextPageFilterAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Startup.cs
中的服务代码
services.AddDefaultIdentity<User>()
.AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<MyContext>();
我的onModelBuilding代码(ASPIdentity特定代码):
public partial class MyContext : DbContext
{
public MyContext()
{
}
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{
}
public virtual DbSet<User> User { get; set; }
public virtual DbSet<IdentityUserClaim<string>> IdentityUserClaim { get; set; }
public virtual DbSet<IdentityUserToken<string>> IdentityUserToken { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUserClaim<string>>().HasKey(p => new { p.Id });
modelBuilder.Entity<IdentityUserToken<string>>().HasKey(p => new { p.UserId });
}
}
我看到我需要包括更多的键,但是找不到有关关系的任何信息。我用ASPIdentity创建了一个空白的.NetCore MVC应用程序,并在startup.cs
中使用了相同的ASPIdentity配置,但我并不明智,我应该使用哪些键或应该如何构建{{1 }}?
答案 0 :(得分:1)
这是一个老问题,但以防万一其他人需要这个。
我认为您的问题与数据库架构无关。您的 MVC 应用程序的点击事件中的某些内容最终使用了 dbset。Find 不正确。在您的情况下;
var tokenEntity = MyContext.UserTokens.Find(user.Id)
相反,您可以使用 Linq;
var tokenEntity = MyContext.UserTokens.FirstOrDefault(ut => ut.UserId == user.Id);
也添加;
using System.Linq
答案 1 :(得分:0)
这篇文章极大地帮助了理解不同的Identity属性之间的关系:https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/existing-db
使用Microsoft文章中提供的相关信息和模板,我能够克服上述问题。
DbContext OnModelCreating方法:
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne(e => e.User)
.HasForeignKey(uc => uc.UserId)
.IsRequired();
// Each User can have many UserLogins
b.HasMany(e => e.Logins)
.WithOne(e => e.User)
.HasForeignKey(ul => ul.UserId)
.IsRequired();
// Each User can have many UserTokens
b.HasMany(e => e.Tokens)
.WithOne(e => e.User)
.HasForeignKey(ut => ut.UserId)
.IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.User)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
modelBuilder.Entity<ApplicationRole>(b =>
{
// Each Role can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
// Each Role can have many associated RoleClaims
b.HasMany(e => e.RoleClaims)
.WithOne(e => e.Role)
.HasForeignKey(rc => rc.RoleId)
.IsRequired();
});
modelBuilder.Entity<ApplicationUserLogin>(b =>
{
b.HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId });
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity<ApplicationUserRole>(b =>
{
b.HasKey(r => new { r.UserId, r.RoleId });
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity<ApplicationUserToken>(b =>
{
b.HasKey(t => new { t.UserId, t.LoginProvider, t.Name });
b.ToTable("AspNetUserTokens");
});
(我用自定义属性创建了自己的ApplicationUser
类)