.NET 6 Identity添加迁移时int外键与主键类型不兼容报错
问题根源
报错核心原因是Klienti实体继承了ASP.NET Core Identity默认的IdentityUser基类,该基类自带类型为string的主键属性Id。你虽然在Klienti中定义了int类型的KlientiId,但既没有显式配置该属性为主键,也没有修改Identity默认的主键类型规则,EF Core在配置关系时会自动将基类的string类型Id识别为Klienti的主键,和MyCart中int类型的外键KlientiId类型不匹配,最终触发报错。
修复方案
二选一即可:
方案1:沿用Identity默认的string类型主键
直接将MyCart实体中的外键属性类型修改为和主键一致:public partial class MyCart { public int CartItemId { get; set; } // 外键类型从int改为string public string KlientiId { get; set; } public int FoodId { get; set; } public virtual Food Food { get; set; } = null!; public virtual Klienti Klienti { get; set; } = null!; }修改后重新生成迁移即可,EF Core会自动识别类型匹配的外键关系。
方案2:使用int类型作为用户实体主键(匹配你当前的代码设计)
按以下步骤修改配置:- 修改
Klienti类的继承基类为泛型版本,指定主键类型为int。如果不需要保留自定义的KlientiId属性,可以直接删除该属性,基类会自带int类型的Id属性作为主键:
// 继承的基类从IdentityUser改为IdentityUser<int> public partial class Klienti : IdentityUser<int> { public Klienti() { MyCarts = new HashSet<MyCart>(); } // 若使用基类自带的int类型Id作为主键,可删除自定义的KlientiId属性 // public int KlientiId { get; set; } public string Name { get; set; } = null!; public string Surname { get; set; } = null!; public string Email { get; set; } = null!; public string Password { get; set; } = null!; public string PhoneNumber { get; set; } = null!; public string StreetName { get; set; } = null!; public string ZipCode { get; set; } = null!; public string City { get; set; } = null!; public string Role { get; set; } = null!; public virtual ICollection<MyCart> MyCarts { get; set; } }- 修改Program.cs(或旧版本的Startup.cs)中的Identity服务注册代码,同步指定主键类型为int:
// 原写法一般为services.AddDefaultIdentity<Klienti>(...) services.AddDefaultIdentity<Klienti>(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles<IdentityRole<int>>() // 角色实体主键同步指定为int .AddEntityFrameworkStores<你的应用DbContext类型, int>(); // 第二个泛型参数指定主键为int类型- 检查Fluent API配置:你当前写的
entity.HasOne(d => d.Klienti).WithMany(p => p.MyCarts).HasForeignKey(d => d.KlientiId)逻辑不需要改动,如果之前删除了自定义的KlientiId属性、改用基类的Id作为主键,把外键配置里的d.KlientiId改成d.KlientiId(对应外键列名)或者调整属性名和主键对齐即可。 - 如果之前已经生成过迁移或创建过数据库,先删除旧的迁移文件、清理数据库中已有的Identity相关表,再重新执行
Add-Migration生成新的迁移文件即可。
- 修改
补充说明:如果坚持要保留自定义的
KlientiId属性作为主键、不使用Identity基类提供的Id属性,只需要在modelBuilder.Entity<Klienti>的配置块中显式加一行entity.HasKey(e => e.KlientiId);,同时把Klienti的继承改成IdentityUser<int>即可,但这种写法不符合Identity的默认约定,后续维护成本更高,不推荐。
内容的提问来源于stack exchange,提问作者Daxrsa
相关产品推荐
相关产品推荐

