首页 新闻 会员 周边

EF Core 生成的 INSERT SQL 中出现重复字段

0
悬赏园豆:30 [已解决问题] 解决于 2023-08-15 15:06

这是在将一个 .NET 5.0 项目升级到 .NET 7.0 后遇到的问题,实体映射关系是这么配置的

b.HasOne(x => x.ParentMessage)
    .WithMany()
    .HasForeignKey("ParentID").IsRequired(false)
    .OnDelete(DeleteBehavior.Cascade);

运行时出现下面的错误日志

The column name 'ParentID' is specified more than once in the SET clause or column list of an INSERT. A column cannot be assigned more than one value in the same clause. Modify the clause to make sure that a column is updated only once.

EF Core 生成的 SQL 语句如下

INSERT INTO [Messages] ([ParentID], [ParentId], [RecipientId], [SenderId])
OUTPUT INSERTED.[ID]
VALUES (@p0, @p1, @p2, @p3, @p4);"

请问如何解决这个问题?

dudu的主页 dudu | 高人七级 | 园豆:30994
提问于:2023-08-15 13:38
< >
分享
最佳答案
0

这个问题的根本原因是在实体映射配置中,对于 ParentID 字段定义了两次映射。一次是通过 .HasForeignKey("ParentID"),另一次是通过 .HasForeignKey("ParentId")。这就导致在生成的 SQL 语句中,ParentID 被列出两次,然后在 INSERT 语句中出现了重复赋值的问题。

要解决这个问题,你需要确保在实体映射关系配置中只定义一次 ParentID 字段映射。在你的代码中,由于是 .HasForeignKey("ParentID") 后面有多余的 ParentID 映射,这是造成问题的地方。

正确的配置应该是:

csharp
Copy code
b.HasOne(x => x.ParentMessage)
.WithMany()
.HasForeignKey("ParentID") // 只需要定义一次字段映射
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade);
注意,我删除了多余的 .HasForeignKey("ParentId"),只保留了一次 HasForeignKey("ParentID")。

修正配置后,再次运行你的代码,应该不会再遇到重复赋值的问题。

——来自 ChatGPT 3.5

收获园豆:30
echo_lovely | 小虾三级 |园豆:1437 | 2023-08-15 14:08

一模一样啊,奇怪
我再问问

echo_lovely | 园豆:1437 (小虾三级) | 2023-08-15 14:09

根据您提供的信息,问题似乎是在将 .NET 5.0 项目升级到 .NET 7.0 后,使用 Entity Framework Core (EF Core) 进行实体映射时出现了问题。错误表明在 INSERT 语句的 SET 子句或列列表中多次指定了列名 'ParentID',导致在同一子句中无法为列分配多个值。

从您提供的代码和错误信息来看,问题可能与映射配置中的 .HasForeignKey("ParentID") 以及数据库模式的变化有关。

为了解决这个问题,您可以尝试以下步骤:

  1. 检查数据库模式变化: 在将项目从 .NET 5.0 升级到 .NET 7.0 时,数据库模式可能发生了变化。检查一下数据库模式是否与之前一致,特别是与 Messages 表的结构和字段名是否匹配。

  2. 检查实体映射配置: 检查您的实体映射配置,确保在升级到 .NET 7.0 后没有出现任何冲突或错误。查看您的 Messages 实体类,确保与 .HasForeignKey("ParentID") 相关的配置正确。

  3. 更新映射配置: 根据您升级到 .NET 7.0 后的数据库模式变化,可能需要更新实体映射配置以适应新的结构。如果数据库模式中的 ParentID 列名发生了变化,您需要相应地更新映射配置中的列名。

以下是可能的解决方法之一,假设数据库模式中的 ParentID 列名已更改为 ParentId(与错误日志中的 SQL 查询中的列名一致)。请注意,根据您的实际情况可能需要做适当的调整:

b.HasOne(x => x.ParentMessage)
    .WithMany()
    .HasForeignKey(x => x.ParentId)  // 更新为正确的列名
    .IsRequired(false)
    .OnDelete(DeleteBehavior.Cascade);

确保将映射配置中的列名与数据库模式的实际列名匹配,这将有助于解决多次分配值的问题。

最后,请务必备份您的数据和代码,以防止意外修改造成数据丢失或其他问题。如果问题仍然存在,您可能需要深入调查和调试数据库模式、映射配置以及数据操作过程中的问题。

echo_lovely | 园豆:1437 (小虾三级) | 2023-08-15 14:10

他好像说,你

INSERT INTO [Messages] ([ParentID], [ParentId], [RecipientId], [SenderId])
OUTPUT INSERTED.[ID]
VALUES (@p0, @p1, @p2, @p3, @p4);

INSERT 了两个 ParentID 导致的……

echo_lovely | 园豆:1437 (小虾三级) | 2023-08-15 14:12

@echo_lovely:

检查实体映射配置: 检查您的实体映射配置,确保在升级到 .NET 7.0 后没有出现任何冲突或错误。查看您的 Messages 实体类,确保与 .HasForeignKey("ParentID") 相关的配置正确。

这句话让我立刻想到出现问题之前将 Message 的 ParentID 属性改名为 ParentId,原来是定义映射关系时大小写不匹配引起的,数据库用的是 SQL Server,大小写不影响。

改为下面的代码解决了,如果之前用 nameof,就会避免这个问题,在 rename 时 visual studio 会自动一起改过来。

b.HasOne(x => x.ParentMessage)
    .WithMany()
    .HasForeignKey(nameof(Message.ParentId))
    .IsRequired(false)
    .OnDelete(DeleteBehavior.Cascade);
dudu | 园豆:30994 (高人七级) | 2023-08-15 15:06
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册