AspNetCore.Identity userManager.FindByNameAsync 在找到所述用户时抛出访问冲突异常
AspNetCore.Identity userManager.FindByNameAsync throws Access Violation Exception upon finding said user
我正在使用 Identity 和 JWT 令牌制作一个简单的用户注册端点。使用 userManager.FindByNameAsync(username) 时,如果没有找到任何用户,它会按预期工作 returning null 并继续注册过程。如果已经存在具有相同用户名的用户,它会抛出访问冲突异常并且服务器停止。
这是我为了测试目的硬编码方法参数的验证:
User userExists = await _userManager.FindByNameAsync("Andrew");
if (userExists != null)
throw new Exception("User already exists");
来自数据访问层的自定义 IdentityUser:
public class User : IdentityUser
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public DateTime JoinedAt {
get { return DateTime.Now; }
set { JoinedAt = value; }
}
public ICollection<ExampleEntity>? ExampleEntities { get; set; }
public ExampleEntity? ExampleEntity { get; set; }
public ICollection<ExampleEntity>? ExampleEntities2 { get; set; }
}
以及身份和 ExampleEntity 的 AppDbContext
public class AppDbContext : IdentityDbContext<User>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<User>()
.HasMany(j => j.ExampleEntities)
.WithOne(j => j.User);
builder.Entity<Property>()
.HasMany(p => p.Users)
.WithOne(t => t.ExampleEntity)
.HasPrincipalKey(t => t.Id)
.OnDelete(DeleteBehavior.NoAction);
builder.Entity<ExampleEntity>()
.HasOne(p => p.User)
.WithMany(p => p.ExampleEntities2)
.HasPrincipalKey(t=> t.Id)
.OnDelete(DeleteBehavior.NoAction);
base.OnModelCreating(builder);
}
public override DbSet<User>? Users { get; set; }
public DbSet<ExampleEntity>? ExampleEntities { get; set; }
}
包含查询的错误:
Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (31ms) [Parameters=[@__normalizedUserName_0='?'
(Size = 256)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [a].[Id], [a].[ExampleEntityId], [a].[AccessFailedCount], [a].[BirthDate], [a].[ConcurrencyStamp],
[a].[Email], [a].[EmailConfirmed], [a].[JoinedAt],
[a].[LockoutEnabled], [a].[LockoutEnd], [a].[Name],
[a].[NormalizedEmail], [a].[NormalizedUserName], [a].[PasswordHash],
[a].[PhoneNumber], [a].[PhoneNumberConfirmed], [a].[SecurityStamp],
[a].[TwoFactorEnabled], [a].[UserName]
FROM [AspNetUsers] AS [a]
WHERE [a].[NormalizedUserName] = @__normalizedUserName_0
The program '[30000] HomesForAll.exe' has exited with code 3221225477 (0xc0000005) 'Access violation'.
期望的结果是 userManager.FindByNameAsync("Andrew") 找到已经存在的用户记录,return 它使用用户实体并通过抛出异常来停止注册过程。
我尝试更改 AppDbContext 设置,认为这是因为没有用于 ICollection 的列并且模型不匹配,但无济于事。
代码:
public DateTime JoinedAt {
get { return DateTime.Now; }
set { JoinedAt = value; }
有一个递归 Setter。
这可能是错误的原因。
尝试:
public DateTime JoinedAt { get; set; } = DateTime.Now;
这是相同的逻辑并使用自动 getter / setters。
背景:
请参阅 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-properties 了解 属性 get/set 的概述。
要知道的关键是 属性 和字段之间的区别。字段是存储值的地方。 属性 是 Get / Set 之一或两者的方法,用于访问基础字段。
例如:
长版本是:
private DateTime _joinedAt;
public DateTime JoinedAt
{
get { return _joinedAt; }
set { _joinedAt = value; }
}
在 C# 中,您可以将上述内容实现为自动属性,只需使用(即,get 或 set 方法本身没有主体):
public DateTime JoinedAt { get; set; }
C# 编译器在后台创建 _joinedAt 字段。
在您的示例中,您没有采用自动属性方法,因此获取和设置方法按编码执行。在您的情况下,JoinedAt.Set 由客户端调用:
user.JoinedAt = {somedate};
然后你 Setter 有效调用
this.JoinedAt = value;
其中 re-invokes Setter 无穷无尽。
这会导致无限 call-stack 和内存故障。这是由您遇到的访问冲突错误报告的。
我正在使用 Identity 和 JWT 令牌制作一个简单的用户注册端点。使用 userManager.FindByNameAsync(username) 时,如果没有找到任何用户,它会按预期工作 returning null 并继续注册过程。如果已经存在具有相同用户名的用户,它会抛出访问冲突异常并且服务器停止。 这是我为了测试目的硬编码方法参数的验证:
User userExists = await _userManager.FindByNameAsync("Andrew");
if (userExists != null)
throw new Exception("User already exists");
来自数据访问层的自定义 IdentityUser:
public class User : IdentityUser
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public DateTime JoinedAt {
get { return DateTime.Now; }
set { JoinedAt = value; }
}
public ICollection<ExampleEntity>? ExampleEntities { get; set; }
public ExampleEntity? ExampleEntity { get; set; }
public ICollection<ExampleEntity>? ExampleEntities2 { get; set; }
}
以及身份和 ExampleEntity 的 AppDbContext
public class AppDbContext : IdentityDbContext<User>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<User>()
.HasMany(j => j.ExampleEntities)
.WithOne(j => j.User);
builder.Entity<Property>()
.HasMany(p => p.Users)
.WithOne(t => t.ExampleEntity)
.HasPrincipalKey(t => t.Id)
.OnDelete(DeleteBehavior.NoAction);
builder.Entity<ExampleEntity>()
.HasOne(p => p.User)
.WithMany(p => p.ExampleEntities2)
.HasPrincipalKey(t=> t.Id)
.OnDelete(DeleteBehavior.NoAction);
base.OnModelCreating(builder);
}
public override DbSet<User>? Users { get; set; }
public DbSet<ExampleEntity>? ExampleEntities { get; set; }
}
包含查询的错误:
Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (31ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [a].[Id], [a].[ExampleEntityId], [a].[AccessFailedCount], [a].[BirthDate], [a].[ConcurrencyStamp], [a].[Email], [a].[EmailConfirmed], [a].[JoinedAt], [a].[LockoutEnabled], [a].[LockoutEnd], [a].[Name], [a].[NormalizedEmail], [a].[NormalizedUserName], [a].[PasswordHash], [a].[PhoneNumber], [a].[PhoneNumberConfirmed], [a].[SecurityStamp], [a].[TwoFactorEnabled], [a].[UserName] FROM [AspNetUsers] AS [a] WHERE [a].[NormalizedUserName] = @__normalizedUserName_0 The program '[30000] HomesForAll.exe' has exited with code 3221225477 (0xc0000005) 'Access violation'.
期望的结果是 userManager.FindByNameAsync("Andrew") 找到已经存在的用户记录,return 它使用用户实体并通过抛出异常来停止注册过程。 我尝试更改 AppDbContext 设置,认为这是因为没有用于 ICollection 的列并且模型不匹配,但无济于事。
代码:
public DateTime JoinedAt {
get { return DateTime.Now; }
set { JoinedAt = value; }
有一个递归 Setter。
这可能是错误的原因。
尝试:
public DateTime JoinedAt { get; set; } = DateTime.Now;
这是相同的逻辑并使用自动 getter / setters。
背景:
请参阅 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-properties 了解 属性 get/set 的概述。
要知道的关键是 属性 和字段之间的区别。字段是存储值的地方。 属性 是 Get / Set 之一或两者的方法,用于访问基础字段。
例如:
长版本是:
private DateTime _joinedAt;
public DateTime JoinedAt
{
get { return _joinedAt; }
set { _joinedAt = value; }
}
在 C# 中,您可以将上述内容实现为自动属性,只需使用(即,get 或 set 方法本身没有主体):
public DateTime JoinedAt { get; set; }
C# 编译器在后台创建 _joinedAt 字段。
在您的示例中,您没有采用自动属性方法,因此获取和设置方法按编码执行。在您的情况下,JoinedAt.Set 由客户端调用:
user.JoinedAt = {somedate};
然后你 Setter 有效调用
this.JoinedAt = value;
其中 re-invokes Setter 无穷无尽。
这会导致无限 call-stack 和内存故障。这是由您遇到的访问冲突错误报告的。