我目前正在开发一个系统,该系统可以生成和管理站点中图像的缩略图。基本上是为了缩短加载时间,在此之前创建较小的图像,这样就无需为每个请求进行任何预处理或加载原始的大图像。
目前创作工作正常,但是我无法删除图像(原始图像和生成图像)。当我直接从数据库中删除时,通过简单的删除就可以正常工作,但是当我通过代码进行删除时,它是行不通的。
“我的图像”表分为两个类
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. A required relationship is missing. Examine StateEntries to determine the source of the constraint violation.
运行context.SaveChanges()
时引发错误。
我已经尝试包含所有依赖项,例如Content和Variations,并且找不到引发此错误的任何其他原因。
以前,该课程没有自我参考,一切正常。有人知道我能做些什么来解决这个问题吗?
答案 0 :(得分:1)
modelBuilder.Entity<Image>() .ToTable("Images"); modelBuilder.Entity<ImageContent>() .HasKey(x => x.ImageId) .ToTable("Images");
此处执行的操作称为表拆分,也就是说,数据库中有一个表Images
,它被“拆分”为两个实体,Image
和ImageContent
。删除包含拆分表的实体对时,一种实现方法是在包含从属实体的情况下删除 principal 实体。主要实体在映射中定义...
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
而没有(大)内容并通过 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();