c# - 删除自引用类的对象时出现 DbUpdateException

标签 c# asp.net entity-framework

我目前正在开发一个系统来生成和管理站点中图像的缩略图。基本上是为了缩短加载时间,之前创建较小的图像,因此不需要对每个请求进行任何预处理或加载原始大图像。

创建目前工作正常,但我无法删除图像(原始图像和生成图像)。当我直接从数据库中删除时,通过简单的删除就可以正常工作,但是当我通过代码执行时,它就不起作用了。

我的图像表分为两类


public class Image(){
  public int Id{ get; set;}
  public int? MainImageId{ get; set;}; 
  public string Description{ get; set;}
  public virtual Image MainImage{ get; set;}
  public virtual ImageContent Content{ get; set;}
  public virtual ICollection<Image> Variations{ get; set;}
}
public class ImageContent(){
  public int ImageId { get; set; }
  public byte[] Raw { get; set; }
  public virtual Image Image { get; set; }
}

它们构建为

 modelBuilder.Entity<Image>()
  .HasRequired(x => x.Content)
  .WithRequiredDependent(x => x.Image);

modelBuilder.Entity<Image>()
  .ToTable("Images");            

modelBuilder.Entity<ImageContent>()
  .HasKey(x => x.ImageId)
  .ToTable("Images");

modelBuilder.Entity<Image>()
  .HasMany(i => i.Variations)
  .WithOptional(i => i.MainImage)
  .HasForeignKey(v => v.MainImageId);

我的删除函数是

public void Delete(int id){
  var image = context.Set<Image>().Include("Variations").FirstOrDefault(i => i.Id == id);

  if (image != null) {

    foreach(Image variation in image.Variations) {
      context.Set<Image>().Remove(variation);
    }

    context.Set<Image>().Remove(image);

    context.SaveChanges();
  }

}

但是当我运行 Delete 函数时,我得到一个 DbUpdateException 消息,其中包含 Invalid data encountered 消息。缺少必需的关系。检查 StateEntries 以确定违反约束的来源。

context.SaveChanges() 运行时抛出错误。

我已经尝试包括所有依赖项,如内容和变体,但找不到引发此错误的任何其他原因。

以前该类没有自引用,一切正常。有人知道我能做些什么来解决这个问题吗?

最佳答案

 modelBuilder.Entity<Image>()
  .ToTable("Images");            

 modelBuilder.Entity<ImageContent>()
  .HasKey(x => x.ImageId)
  .ToTable("Images");

你在这里做的事情叫做分表,也就是说,数据库中只有一张表,Images。 ,即“拆分”为两个实体,ImageImageContent .删除包含拆分表的实体对时,一种方法是删除主要 实体,同时包含从属实体。主体实体在映射中定义...

 modelBuilder.Entity<Image>()
  .HasRequired(x => x.Content)
  .WithRequiredDependent(x => x.Image);

上面写着:Image是相关的,所以 ImageContent是校长。

问题来了。

这条线...

 context.Set<Image>().Remove(image);

...删除依赖实体。

现在您可以通过包含 Content 轻松解决此问题并将其标记为删除(暂时忽略 Variations):

using System.Data.Entity;
...

var image = context.Set<Image>().Include(i => i.Content)
                   .Single(i => i.Id == id);
context.Entry(image).State = EntityState.Deleted;
context.Entry(image.Content).State = EntityState.Deleted;

但我认为该模型在 Image 时更有意义是主要实体:

modelBuilder.Entity<Image>()
  .HasRequired(x => x.Content)
  .WithRequiredPrincipal(x => x.Image);

现在可以删除图像而无需显式删除 Content :

var image = context.Set<Image>().Include(i => i.Content)
                   .Single(i => i.Id == id);
context.Entry(image).State = EntityState.Deleted;
// or context.Set<Image>().Remove(image);

这也使得删除变体变得更容易:

var image = context.Set<Image>()
                   .Include(i => i.Content)
                   .Include(i => i.Variations.Select(v => v.Content))
                   .Single(i => i.Id == id);

foreach (var variation in image.Variations)
{
    context.Set<Image>().Remove(variation);
}
context.Set<Image>().Remove(image);

作为奖励,这还使您能够通过仅获取 Image 来降低删除成本。 s 从数据库中取出,没有它们的(大)内容,并通过 stub 实体删除内容。我将向您展示如何仅针对一张图片执行此操作:

var img1 = context.Set<Image>(). Single(i => i.Id == 1);
img1.Content = new ImageContent { ImageId = img1.Id }; // Stub entity
context.Entry(img1.Content).State = Entity.EntityState.Unchanged; // Attach to context
context.Set<Image>().Remove(img1);
context.SaveChanges();

关于c# - 删除自引用类的对象时出现 DbUpdateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56296335/

相关文章:

c# - 一个数据库具有多个上下文的 EF Initializer

entity-framework - EF6 在更新时将日期时间设置为 Null

c# - 使用C#识别 “GridViewCellEditEndedEvent”中的选定行

c# - DataTrigger 不会更改 Text 属性

javascript - 使用 jQuery 验证插件匹配两个字段

c# - MVC3 maproute 不显示操作?

asp.net - 自动部署到多个生产环境

c# - 从 SQL Server 插入到 Access

c# - 在 MVC 2 中,如何使用 C# 确定服务器上是否存在文件?

c# - 使用 asp.net-mvc2 和 Entity Framework 编辑和更新复杂 View 模型对象的正确方法