我目前正在开发一个系统来生成和管理站点中图像的缩略图。基本上是为了缩短加载时间,之前创建较小的图像,因此不需要对每个请求进行任何预处理或加载原始大图像。
创建目前工作正常,但我无法删除图像(原始图像和生成图像)。当我直接从数据库中删除时,通过简单的删除就可以正常工作,但是当我通过代码执行时,它就不起作用了。
我的图像表分为两类
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
。 ,即“拆分”为两个实体,Image
和 ImageContent
.删除包含拆分表的实体对时,一种方法是删除主要 实体,同时包含从属实体。主体实体在映射中定义...
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/