EF Core -使用TPT方法不能保存一个以上的实体



我们正在将我们的应用程序。net Framework和。EF6迁移到。net 6和。EF Core v6。

我们的应用程序在我们的一个模型中使用TPT方法。我已经阅读了所有与TPT相关的文章,并在SO上提出了一些问题,但似乎它并没有解决我的问题。

我有一个基于这篇文章的示例代码。

public class TPTUser
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
public class TPTStudent : TPTUser
{
public string CGPA { get; set; }
public string Major { get; set; }
}
public class TPTTeacher : TPTUser
{
public string Designation { get; set; }
public string Speciality { get; set; }
}

我DbContext:

public class TestContext : DbContext
{
public DbSet<TPTUser> TPTUsers { get; set; }
public DbSet<TPTStudent> TPTStudents { get; set; }
public DbSet<TPTTeacher> TPTTeachers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Foo");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TPTUser>().ToTable("TPTUsers");
modelBuilder.Entity<TPTUser>()
.HasKey(p => p.Id);
modelBuilder.Entity<TPTUser>()
.Property(p => p.Id)
.ValueGeneratedOnAdd()
.UseIdentityColumn();
modelBuilder.Entity<TPTStudent>().ToTable("TPTStudents");
modelBuilder.Entity<TPTTeacher>().ToTable("TPTTeachers");
}
}

我试图添加2TPTStudent实例与PK具有一个值(这只是一个随机的int值)。最初,我们的应用程序从客户端生成模型,默认情况下,它在PK上有一个值。

这是添加TPTStudent的代码:
static void Main(string[] args)
{
using (var context = new TestContext())
{
var std = new List<TPTStudent>
{
new TPTStudent()
{
Id = 422,
Username = Guid.NewGuid().ToString("N"),
Email = Guid.NewGuid().ToString("N"),
CGPA = Guid.NewGuid().ToString("N"),
Major = Guid.NewGuid().ToString("N")
},
new TPTStudent()
{
Id = 412,
Username = Guid.NewGuid().ToString("N"),
Email = Guid.NewGuid().ToString("N"),
CGPA = Guid.NewGuid().ToString("N"),
Major = Guid.NewGuid().ToString("N")
}
};
context.TPTStudents.AddRange(std);
context.SaveChanges();
}
}

点击SaveAsync后,它返回这个错误:

Cannot insert explicit value for identity column in table 'TPTUsers' when IDENTITY_INSERT is set to OFF

我知道这个问题的原因是EF Core假设如果你设置键值,那么这就是那个实体的键值。

我的主要目标是成功地添加这些实体和EF Core忽略值Id属性。Id的值需要在数据库中生成,因为它的列被设置为IDENTITY。

我试过使用ValueGeneratedOnAdd,UseIdentityColumn,设置IsTemporary为true (SaveChanges之前),但似乎都不起作用。

如果我想达到的目标是不可能的,那么我最后的办法就是这个方法。

编辑:我发现这个问题,这正是我所需要的。有人知道如何在EF Core v6上实现这个吗?

同样的事情也发生在我身上。问题是,id随着数据库的增加而增加,另一方面,实体框架试图插入相同的id。首先,您可以通过禁用数据库的自动增量来解决这个问题。或者你可以采用我的第二个解决方案。

我是怎么解决的

public class TPHUser
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}

模型应该是这样的。此外,您应该启用标识插入。然后应该插入数据,之后应该禁用身份插入。但最重要的是,您应该在一个事务中完成它,以保持数据一致性。下面的代码用于事务插入。我正在使用unitOfWork。但是如果你愿意,你也可以使用没有unitOfWork的相同代码。

using (var transaction = unitOfWork._context.Database.BeginTransaction())
{
await unitOfWork._context.Database.ExecuteSqlRawAsync("SET IDENTITY_INSERT TPHUser ON");
var std = new List<TPTStudent>
{
new TPTStudent()
{
Username = Guid.NewGuid().ToString("N"),
Email = Guid.NewGuid().ToString("N"),
CGPA = Guid.NewGuid().ToString("N"),
Major = Guid.NewGuid().ToString("N")
},
new TPTStudent()
{
Username = Guid.NewGuid().ToString("N"),
Email = Guid.NewGuid().ToString("N"),
CGPA = Guid.NewGuid().ToString("N"),
Major = Guid.NewGuid().ToString("N")
}
}
var ss = await unitOfWork.TPTStudent_Repostory.AddRange(std);
await unitOfWork.CompleteAsync();
await unitOfWork._context.Database.ExecuteSqlRawAsync("SET IDENTITY_INSERT TPHUser OFF");
transaction.Commit();
}

相关内容

最新更新