gpt4 book ai didi

c# - 添加相关实体时报错 "Database operation expected to affect 1 row(s) but actually affected 0 row(s)"

转载 作者:行者123 更新时间:2023-12-05 01:25:02 31 4
gpt4 key购买 nike

我一直在寻找一种在 EF Core 中编写“通用”更新方法的解决方案,该方法更新实体的所有已更改属性,包括相关集合。这样做的原因是我将实体名称的翻译存储在不同的表中。我找到了 this解决方案一开始似乎工作得很好,但后来我注意到当我在实体中唯一改变的是添加时,我收到错误“数据库操作预计会影响 1 行但实际上影响 0 行”相关表 TblProjectTranslations 中的新名称翻译。这是我的代码:

public async Task UpdateProjectAsync(TblProject updatedEntity)
{
TblProject dbEntity = Context.TblProjects
.Include(dbEntity => dbEntity.TblProjectTranslations)
.SingleOrDefault(dbEntity => dbEntity.ProjectId == updatedEntity.ProjectId);

if (dbEntity != null)
{
Context.Entry(dbEntity).CurrentValues.SetValues(updatedEntity);

foreach (TblProjectTranslation dbTranslation in dbEntity.TblProjectTranslations.ToList())
{
if (!updatedEntity.TblProjectTranslations
.Any(translation => translation.ProjectId == dbTranslation.ProjectId && translation.Language == dbTranslation.Language))
{
Context.TblProjectTranslations.Remove(dbTranslation);
}
}

foreach (TblProjectTranslation newTranslation in updatedEntity.TblProjectTranslations)
{
TblProjectTranslation dbTranslation = dbEntity.TblProjectTranslations
.SingleOrDefault(dbTranslation => dbTranslation.ProjectId == newTranslation.ProjectId && dbTranslation.Language == newTranslation.Language);

if (dbTranslation != null)
{
Context.Entry(dbTranslation).CurrentValues.SetValues(newTranslation);
}
else
{
dbEntity.TblProjectTranslations.Add(newTranslation);
}
}

await Context.SaveChangesAsync();
}
}

以下是反向工程的 EF Core 类:

public partial class TblProject
{
public TblProject()
{
TblProjectTranslations = new HashSet<TblProjectTranslation>();
}

public int ProjectId { get; set; }

public virtual ICollection<TblProjectTranslation> TblProjectTranslations { get; set; }
}

public partial class TblProjectTranslation
{
public int ProjectId { get; set; }
public string Language { get; set; }
public string ProjectName { get; set; }

public virtual TblProject Project { get; set; }
}

下面是它们在 OnModelCreating 中的定义方式:

modelBuilder.Entity<TblProject>(entity =>
{
entity.HasKey(e => e.ProjectId);

entity.ToTable("TBL_project");

entity.Property(e => e.ProjectId).HasColumnName("project_ID");
});

modelBuilder.Entity<TblProjectTranslation>(entity =>
{
entity.HasKey(e => new { e.ProjectId, e.Language });

entity.ToTable("TBL_project_translation");

entity.HasIndex(e => e.ProjectId, "IX_TBL_project_translation_project_ID");

entity.Property(e => e.ProjectId).HasColumnName("project_ID");

entity.Property(e => e.Language)
.HasMaxLength(5)
.HasColumnName("language")
.HasDefaultValueSql("('-')");

entity.Property(e => e.ProjectName)
.IsRequired()
.HasMaxLength(50)
.HasColumnName("project_name")
.HasDefaultValueSql("('-')");

entity.HasOne(d => d.Project)
.WithMany(p => p.TblProjectTranslations)
.HasForeignKey(d => d.ProjectId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("TBL_project_translation_TBL_project");
});

我不明白的是 dbEntity.TblProjectTranslations.Add(newTranslation) 似乎是问题所在。当我将此行替换为 await Context.TblProjectTranslations.AddAsync(newTranslation) 时,错误“神奇地”消失了,但这两种方式不应该做基本相同的事情吗?下面是一个 updatedEntity 和一个 dbEntity 的示例,我在问题发生之前调试函数时捕获了它们:

updatedEntity:
ProjectId: 41
TblProjectTranslations: 1 Entry with:
Language: "en"
Project: null
ProjectId: 41
ProjectName: "TestNameEN"

dbEntity:
ProjectId: 41
TblProjectTranslations: No entries

这是怎么回事?我什至在这两个表的数据库中都没有任何触发器,这似乎是其他一些人出现此错误的原因。

最佳答案

在试用了示例模型、代码和解释之后,我终于能够重现它。罪魁祸首似乎是复合键及其字符串部分的默认值:

entity.HasKey(e => new { e.ProjectId, e.Language }); // (1)

entity.Property(e => e.Language)
.HasMaxLength(5)
.HasColumnName("language")
.HasDefaultValueSql("('-')"); // (2)

如果你使用也会发生同样的情况

.HasDefaultValue("-")

这种组合以某种方式导致 EF 考虑添加到父集合导航属性的项目

dbEntity.TblProjectTranslations.Add(newTranslation);

作为 Modified 而不是 Added,这后来导致问题中的错误。

因为我在 EF Core 文档中找不到这样的行为解释,而且通常它看起来是错误的,所以我建议去报告给 EF Core GitHub issue tracker .

同时,我看到的可能的解决方法是

  • 删除键列的 .HasDefaultValueSql/.HasDefaultValue

  • 与其将子项添加到父集合,不如将其直接添加到上下文或相应的 DbSet(可选地提前设置引用导航属性“以防万一”):

newTranslation.Project = dbEntity;
Context.Add(newTranslation);

关于c# - 添加相关实体时报错 "Database operation expected to affect 1 row(s) but actually affected 0 row(s)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70988764/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com