同时使用 EF Core DbContext 和 ASP.NET Core Identity 的 UserManager

问题描述 投票:0回答:1

我的用户实体:

public class User : IdentityUser<long>
{
  public Office Office { get; set; }      // not nullable
  // ...other custom properties
}

假设我想创建一个新用户:

var user = new User {
  UserName       = "foo",
  Email          = "[email protected]",
  EmailConfirmed = true,
  Office         = await context.Offices.SingleAsync(x => x.Name == "Head Office"),
};
await _userManager.CreateAsync(user, "password");

抛出:

重复的键值违反了唯一约束“PK_Office”

原因是

Office
在一个上下文中加载并在
UserManager
封装的上下文中使用(它试图创建一个具有相同PK的新上下文)。

底层上下文未公开,因此无法执行

userManager.Context.Attach(office)
或类似操作。

我可以看到两种解决方法:

  • 声明
    User.Office
    为可空,然后:
    var user = ...
    await _userManager.CreateAsync(user, "password");
    user.Office = ...
    _context.Attach(user);
    await _context.SaveChangesAsync();
    
    但我不想这样做:我不想破坏我的域模型(没有办公室,用户就无法存在),因为
    UserManager
  • 的技术限制
  • 我可以通过
    DbContext
    而不是
    UserManager
    创建用户。但我也不想这样做,因为它为我处理所有与身份验证相关的事情,而且我不想承担任何责任。

还有哪些其他选择?

(如果相关:这不是在网络请求的上下文中,而是实际上在控制台应用程序中。)

asp.net-core entity-framework-core dbcontext asp.net-core-identity asp.net-core-7.0
1个回答
0
投票

经过大量调查,我发现:如果

DbContext
UserManager
是从同一个容器解析的,那么后者的底层上下文将与前者是相同的实例。

这对我来说不起作用,因为在我的控制台应用程序中,这两件事是通过两个容器解决的。

最好的选择是确保它们从同一个容器中解析(即

ServiceProvider
)。

如果这不可能,那么还有其他选择:

  • 上面我已经确定的两个
  • @MichałTurczyn 的评论中的另一条:公开
    Office
    实体的 PK,然后
    user.OfficeId = officeId
© www.soinside.com 2019 - 2024. All rights reserved.