我需要在数据库中插入一个enitity,它有一个约束它的id,所以我想手动设置它。
注意:下面的模型是了解我正在做什么的最小例子。整个过程都在使用EF Core和Pomelo MySql提供程序的ASP.NET Core 2上运行。
我试图在我已经存在的数据库(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));
因此Users
表中的每条记录都在UserData
表中有记录。
现在在我的代码中我想使用像
Context.Users.Add(user);
Context.SaveChanges();
data.Id = user.Id;
Context.UserData.Add(data);
Context.SaveChanges();
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`))
这意味着无论Id
传递给MySQL,它都不是User
的那个。
我甚至尝试按Entering keys manually with Entity Framework中的建议向[DatabaseGenerated(DatabaseGeneratedOption.None)]
添加UserData.Id
,但我认为更多关于CodeFirst方法而不是已经在运行数据库中。
从这个问题开始: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);
}
答案 0 :(得分:1)
User
应该获得数据库生成的Id
不符合您的流利配置:
modelBuilder.Entity<User>(entity =>
{
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("int(11)")
.ValueGeneratedNever(); // <-- the problem
}
将ValueGeneratedNever()
替换为ValueGeneratedOnAdd()
,问题将得到解决。
作为旁注,由于您似乎在User
和UserData
中都有导航属性,因此您可以使用它们而不是FK属性,因此无需中间SaveChanges
只需获取生成的Id
。例如,而不是:
Context.Users.Add(user);
Context.SaveChanges();
data.Id = user.Id;
Context.UserData.Add(data);
Context.SaveChanges();
你可以简单地使用:
user.UserData = data;
Context.Users.Add(user); // <-- will also add `UserData`
Context.SaveChanges();
EF将以正确的顺序插入两个记录(首先User
,然后UserData
,并使用上一个插入内容生成的Id
。
答案 1 :(得分:0)
事实证明,在添加新实体并执行
之后VANETZA_DIR
新添加的对象未更新。从数据库中完成新的拉动后
Context.SaveChanges()
返回的实体具有正确的ID,分配给我的Context.Users.First(u => u.Email == user.Email);
已允许正确添加到表格中。