Mar*_*iak 1 c# mysql entity-framework-core asp.net-core-2.0
我需要将一个实体插入数据库,该实体对其 id 有约束,因此我想手动设置它。
注意:下面的模型是了解我正在做的事情的最小示例。整个过程在 ASP.NET Core 2 上运行,并带有 EF Core 和 Pomelo MySql 提供程序。
我正在尝试在现有数据库(MySQL)中创建一个实体,其定义如下:
CREATE TABLE Users (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(128) NOT NULL);
CREATE TABLE UserData (
id INTEGER PRIMARY KEY,
name VARCHAR(32) NOT NULL,
FOREIGN KEY(id) REFERENCES Users(id));
Run Code Online (Sandbox Code Playgroud)
所以Users表中的每条记录在表中都有一条记录UserData。现在在我的代码中我想使用类似的东西
Context.Users.Add(user);
Context.SaveChanges();
data.Id = user.Id;
Context.UserData.Add(data);
Context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
它们User应该Id由数据库生成,然后UserData用它创建Id。然而,EF执行的语句会导致错误:
Failed executing DbCommand (6ms) [Parameters=[@p0='?', @p1='?' (Size = 32)], CommandType='Text', CommandTimeout='30']
INSERT INTO `UserData` (`id`, `name`)
VALUES (@p0, @p1);
MySql.Data.MySqlClient.MySqlException: Cannot add or update a child row:
a foreign key constraint fails (`Main`.`UserData`, CONSTRAINT `UserData_ibfk_1`
FOREIGN KEY (`id`) REFERENCES `Users` (`id`))
Run Code Online (Sandbox Code Playgroud)
这意味着无论Id传递到 MySQL 的是什么,它都不是User.
我什至尝试按照使用 Entity Framework 手动输入键中的建议添加[DatabaseGenerated(DatabaseGeneratedOption.None)]a ,但我认为这更多是关于 CodeFirst 方法,而不是拥有一个已经运行的数据库。UserData.Id
从这个问题:EF Core Add function returns negative id我了解到Context.Add()它修改了Id,但在之后分配我的值Add不会改变任何东西。
如果它很重要,这是我的 DbContext 配置
modelBuilder.Entity<UserData>(entity =>
{
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("int(11)")
.ValueGeneratedNever();
entity.Property(e => e.Name)
.IsRequired()
.HasColumnName("name")
.HasMaxLength(32);
entity.HasOne(d => d.User)
.WithOne(p => p.UserData)
.HasForeignKey<UserData>(d => d.Id)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("UserData_ibfk_1");
}
modelBuilder.Entity<User>(entity =>
{
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("int(11)")
.ValueGeneratedNever();
entity.Property(e => e.Email)
.IsRequired()
.HasColumnName("email")
.HasMaxLength(128);
}
Run Code Online (Sandbox Code Playgroud)
应该由数据库
User生成Id
不根据您的流畅配置:
modelBuilder.Entity<User>(entity =>
{
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("int(11)")
.ValueGeneratedNever(); // <-- the problem
}
Run Code Online (Sandbox Code Playgroud)
替换ValueGeneratedNever()为ValueGeneratedOnAdd(),问题就解决了。
作为旁注,由于您似乎在 和 中都有导航属性User,UserData因此您可以使用它们而不是 FK 属性,从而消除了中间的需要,SaveChanges只是获取生成的Id。例如,而不是:
Context.Users.Add(user);
Context.SaveChanges();
data.Id = user.Id;
Context.UserData.Add(data);
Context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
你可以简单地使用:
user.UserData = data;
Context.Users.Add(user); // <-- will also add `UserData`
Context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
EF 将以正确的顺序插入两条记录(首先插入User,然后插入上一次插入生成的UserData记录Id)。