我在AspNetCore.Identity
应用程序中使用了Asp.Net Core
,我想调用名为FindByLoginAsync
的方法,但结果始终为NULL。
版本:
Microsoft.AspNetCore.Identity.EntityFrameworkCore (1.1.1)
Microsoft.AspNetCore.Identity (1.1.1)
代码:
var loginProvider = "Github"
var providerKey = "1234567";
var user = await _userManager.FindByLoginAsync(loginProvider, providerKey);
此记录存在于数据库中,但此方法始终返回NULL。
我试过跟踪SQL查询,我得到了这个:
exec sp_executesql N'SELECT TOP(1) [e].[ProviderKey], [e].[LoginProvider], [e].[ProviderDisplayName], [e].[UserId]
FROM [UserLogins] AS [e]
WHERE ([e].[ProviderKey] = @__get_Item_0) AND ([e].[LoginProvider] = @__get_Item_1)',N'@__get_Item_0 nvarchar(450),@__get_Item_1 nvarchar(450)',@__get_Item_0=N'Github',@__get_Item_1=N'1234567'
我的SQL查询与[e].[LoginProvider]
的值providerKey
和[e].[ProviderKey]
的值loginProvider
类似。
应用程序DbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(i =>
{
i.ToTable("Users");
i.HasKey(x => x.Id);
});
builder.Entity<ApplicationRole>(i =>
{
i.ToTable("Roles");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserRole<int>>(i =>
{
i.ToTable("UserRoles");
i.HasKey(x => new { x.RoleId, x.UserId });
});
builder.Entity<IdentityUserLogin<int>>(i =>
{
i.ToTable("UserLogins");
i.HasKey(x => new { x.ProviderKey, x.LoginProvider });
});
builder.Entity<IdentityRoleClaim<int>>(i =>
{
i.ToTable("RoleClaims");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserClaim<int>>(i =>
{
i.ToTable("UserClaims");
i.HasKey(x => x.Id);
});
builder.Entity<IdentityUserToken<int>>(i =>
{
i.ToTable("UserTokens");
i.HasKey(x => x.UserId);
});
}
}
IdentityUser的实现,IdentityRole
public class ApplicationUser : IdentityUser<int>
{
}
public class ApplicationRole : IdentityRole<int>
{
}
我该如何解决这个问题?这种行为怎么可能? :)
谢谢。
答案 0 :(得分:1)
在注册实体IdentityUserLogin
时,您的主键顺序不正确。将其更改为此
builder.Entity<IdentityUserLogin<int>>(i =>
{
i.ToTable("UserLogins");
i.HasKey(x => new { x.LoginProvider, x.ProviderKey });
});
这是修复,现在背后的理由。
在版本1.1.1中,方法UserStore.FindByLoginAsync
使用方法DbSet.FindAsync
,它接受主键的有序值数组。订单必须遵循实体注册中使用的订单。
public async virtual Task<TUser> FindByLoginAsync(string loginProvider, string providerKey,
CancellationToken cancellationToken = default(CancellationToken))
{
...
var userLogin = await UserLogins.FindAsync(new object[] { loginProvider, providerKey }, cancellationToken);
...
}
在默认实现中,主键在correct order
中注册builder.Entity<TUserLogin>(b =>
{
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
b.ToTable("AspNetUserLogins");
});