EF核心 - 从表继承的问题,并在下一个表中使用主键
我尝试使用 TPT 创建数据库。我有九个实体,但当我启动 DbInitializer 时,它给出以下异常
“System.InvalidOperationException:'无法跟踪实体类型'Boss'的实例,因为已跟踪具有相同键值 {'UserId'} 的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例,请考虑使用“,但有时我会遇到此异常。 “当身份插入设置为关闭时,无法在表中插入身份列的显式值”
我使用了 TPT,因为我的老板和员工继承自用户,但我在老板的公司中使用相同的密钥。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Boss>()
.HasOne(c => c.Company)
.WithOne(b => b.Boss)
.HasForeignKey<Company>(c => c.UserId);
modelBuilder.Entity<LevelSpecializationOfAdvance>()
.HasKey(ls => new { ls.SpecializationId, ls.LevelOfAdvanceId, ls.UserId});
modelBuilder.Entity<LevelSpecializationOfAdvance>()
.HasOne(e => e.Employee)
.WithMany(l => l.LevelSpecializationOfAdvances)
.HasForeignKey(e => e.UserId);
modelBuilder.Entity<Boss>().ToTable("Bosses");
modelBuilder.Entity<Employee>().ToTable("Employees");
}
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public int RoleId { get; set; }
public virtual Role Role { get; set; }
}
public class Boss : User
{
public string UniqueCode { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string NIP { get; set; }
public string CompanyName { get; set; }
public string Code { get; set; }
public virtual List<Employee> Employees { get; set; }
public int UserId { get; set; }
public virtual Boss Boss { get; set; }
}
public class Employee: User
{
public int PhoneNumber { get; set; }
public int CompanyId { get; set; }
public List<LevelSpecializationOfAdvance> LevelSpecializationOfAdvances { get; set; }
}
DBInitializer 屏幕中的代码
if (!context.Users.Any())
{
var users = GetUsers();
context.AddRange(users);
context.SaveChanges();
}
if(!context.Bosses.Any())
{
var bosses = GetBosses();
context.AddRange(bosses);
context.SaveChanges();
}
public IEnumerable<Boss> GetBosses()
{
var bosses = new List<Boss>()
{
new Boss()
{
UserId = 2,
UniqueCode = "test"
}
};
return bosses;
}
以及数据库中的键
I tried to create database using TPT. I have nine entities but when i launch DbInitializer its give me following exception
"System.InvalidOperationException: 'The instance of entity type 'Boss' cannot be tracked because another instance with the same key value for {'UserId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using " but sometimes i have this exception
"cannot insert explicit value for identity column in table when identity insert is set to off"
I used TPT becouse my Bosses and Employees inheritance from User but i use the same key in the Companies from Bosses.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Boss>()
.HasOne(c => c.Company)
.WithOne(b => b.Boss)
.HasForeignKey<Company>(c => c.UserId);
modelBuilder.Entity<LevelSpecializationOfAdvance>()
.HasKey(ls => new { ls.SpecializationId, ls.LevelOfAdvanceId, ls.UserId});
modelBuilder.Entity<LevelSpecializationOfAdvance>()
.HasOne(e => e.Employee)
.WithMany(l => l.LevelSpecializationOfAdvances)
.HasForeignKey(e => e.UserId);
modelBuilder.Entity<Boss>().ToTable("Bosses");
modelBuilder.Entity<Employee>().ToTable("Employees");
}
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public int RoleId { get; set; }
public virtual Role Role { get; set; }
}
public class Boss : User
{
public string UniqueCode { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string NIP { get; set; }
public string CompanyName { get; set; }
public string Code { get; set; }
public virtual List<Employee> Employees { get; set; }
public int UserId { get; set; }
public virtual Boss Boss { get; set; }
}
public class Employee: User
{
public int PhoneNumber { get; set; }
public int CompanyId { get; set; }
public List<LevelSpecializationOfAdvance> LevelSpecializationOfAdvances { get; set; }
}
Code in DBInitializer
if (!context.Users.Any())
{
var users = GetUsers();
context.AddRange(users);
context.SaveChanges();
}
if(!context.Bosses.Any())
{
var bosses = GetBosses();
context.AddRange(bosses);
context.SaveChanges();
}
public IEnumerable<Boss> GetBosses()
{
var bosses = new List<Boss>()
{
new Boss()
{
UserId = 2,
UniqueCode = "test"
}
};
return bosses;
}
Screen with keys in the database
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
“当身份插入设置为关闭时,无法在表中插入身份列的显式值”
而不是:
执行:
如果您的表配置了自动增量(每个新实体都会根据上次插入的实体获取生成的主键)并且您使用 .Add() 或 .AddRange() 时,您不应指定主键值(因为自动增量意味着它会为您生成)。
请注意,这仅适用于使用 EF 时。如果您正在编写 SQL 代码,则还应该指定主键值。
创建实体时,请始终记住也放置其关系数据。 Boss 模型有一个外键 RoleId,因为它继承自模型 User。默认情况下外键不能为 NULL。
此外,您创建关系的方式是,单个角色可以由许多用户拥有,但一个用户不能拥有多个角色。这意味着用户只能拥有管理员/卖家或高级角色。一个用户不能拥有超过 1 个角色。
考虑创建一个多对多表,以便您可以选择为单个用户提供多个角色。例如,您可以拥有不具有高级角色的卖家和具有高级角色的卖家,并在此基础上您可以实现其他逻辑。
"Cannot insert explicit value for identity column in table when identity insert is set to off"
Instead of:
Do:
If your table is configured with Auto-increment (each new entity gets a generated primary key based on the last inserted one) and you are using .Add() or .AddRange() you should NOT specify a primary key value (because again, auto-increment means that it gets generated for you).
Note that this is only when you are using EF. If instead you were writing SQL code you should specify the primary key value as well.
When creating an entity, always remember to put its relationship data as well. The Boss model has a foreign key RoleId, because it inherits from the model User. By default foreign keys can NOT be NULL.
Also the way you've created your relationships a single role can be owned by many users, but one user wouldn't be able to have many roles. That means a user can only have an Admin/Seller or Premium role for example. A user can NOT have more than 1 role.
Consider making a many to many table so you can have the option of giving a single user many roles. For example you can have Sellers without the Premium role and Sellers with the Premium role and based on that you can implement additional logic.