我知道这个问题已经被问了很多次,但我看到的所有答案似乎都与所讨论的实体有关,这些实体来自与当前不同的上下文,例如ASP.NET MVC等客户端/服务器场景。
在我的情况下,这不是真的,因为所有的操作都发生在一个代码块中。如果有什么不同的话,这一切都在Blazor服务器端应用程序中。
我使用的是ASP.NET Identity,其Identity模型名为User
。我有一个History
模型(为了清晰起见,删除了不相关的属性(。。。
public class History {
public int Id { get; set; }
public string UserID { get; set; }
[ForeignKey(nameof(UserID))]
public virtual User User { get; set; }
}
我正在尝试创建一个新的History
项目,如下所示。。。
string email = (await AuthenticationStateProvider.GetAuthenticationStateAsync())
.User.Identity.Name.ToLower();
User user = await Context.Users.SingleAsync(u => u.Email.ToLower() == email);
History h = new() {
// Other properties removed for clarity
UserID = user.Id,
};
Context.Histories.Add(h);
await Context.SaveChangesAsync();
但这是一个例外。。。
违反PRIMARY KEY约束"PK_AspNetUsers"。无法在对象"dbo.AspNetUsers"中插入重复的密钥。重复的密钥值为…
正如您所看到的,所有代码都发生在一个块中,因此从数据库中检索的User
实体和我试图保存的新创建的History
实体都应该在同一上下文中。我不明白它为什么要添加一个新的User
。
上下文以常规方式注入到Blazor组件中。。。
[Inject]
private ApplicationDbContext Context { get; set; }
并且在CCD_ 7中设置如下。。。
services.AddDbContext<ApplicationDbContext>(options => {
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
options.EnableSensitiveDataLogging();
options.EnableDetailedErrors();
}, ServiceLifetime.Transient);
这是一个相当成熟的应用程序,在其他地方做这种事情似乎都很好,只是这个新的History
项目导致了异常,尽管我们在其他地方也做同样的事情。
我试过了。。。
- 将用户的状态设置为未更改
- 检索用户时添加
AsNoTrackingWithIdentityResolution()
- 设置
User
属性而不是UserId
属性 - 保存前将
User
属性设置为null
。。。但这些都无济于事。
作为一个实验,我尝试注入第二个上下文,并使用它来获取用户Id,然后将其处理并设置为null,以确保它不会一直存在。在这个阶段,原始上下文根本没有接触过用户,我有一个带有所需Id的普通字符串。然而,我仍然得到了相同的异常。
有什么想法吗?感谢
唉,原来我不仅叫错了树,而且在错误的森林里!
问题与History
项本身的UserId
属性无关,它是被省略的(看似无害的(其他属性之一(通过参数传入(,具有引用user
的导航属性,这导致了异常。
我修改了代码,忽略了参数,直接从数据库中获取另一个属性,现在一切都很好。
不知道这是否会对任何人有所帮助,但我想我会把它作为一个答案发布,以防万一。