【发布时间】:2017-01-25 17:39:18
【问题描述】:
我有一个使用实体框架映射的 SQLite 数据库。 有 2 个表:Collections (1:n) Albums。
当我删除一个收藏时,所有相关的相册也必须被删除。
我使用CollectionRepo.Delete(collection); 来实现这一点。它使用以下代码:
public int Delete(Collection entity)
{
Context.Entry(entity).State = EntityState.Deleted;
return Context.SaveChanges();
}
问题是:当我执行这段代码时,Context.SaveChanges();给我一个异常:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
似乎实体框架想要在外键上null 而不是删除条目。但这绝对不是我想要的,因为没有父母的专辑毫无意义(至少在我的用例中)。
我显然可以先手动删除相册,然后删除空集合,但在我看来有点棘手。首先,在我看来,EF 应该足够聪明,可以自己完成以简化代码;其次,如果我与收藏和专辑有几十个关系,我最终会得到一个相当大的、难以维护的、代码库。
集合类
public class Collection
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public virtual List<Album> Albums { get; set; } = new List<Album>();
}
专辑类
public class Album
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
[Required]
[ForeignKey("Collection")]
public long CollectionId { get; set; }
public virtual Collection Collection { get; set; }
}
DbContext 子类
public class DataEntities : DbContext
{
public virtual DbSet<Collection> Collections { get; set; }
public virtual DbSet<Album> Albums { get; set; }
public DataEntities() : base("name=Connection")
{
Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Album>()
.HasRequired(a => a.Collection)
.WithMany(c => c.Albums)
.HasForeignKey(a => a.CollectionId)
.WillCascadeOnDelete(true);
modelBuilder.Entity<Collection>()
.HasMany(c => c.Albums)
.WithRequired(a => a.Collection)
.WillCascadeOnDelete(true);
}
}
【问题讨论】:
-
您使用的是哪个版本的 sqlite?听起来这是 sqlite 不支持级联删除 stackoverflow.com/questions/10719425/… 的问题
-
3.14.2 (System.Data.SQLite 1.0.103)。恕我直言,它似乎与 SQLite 无关,因为我表中的外键允许为空,加上异常堆栈跟踪最深调用是
System.Data.Entity.Core.Objects.ObjectContext.PrepareToSaveChanges(SaveOptions options)似乎与 SQLite 无关。 -
您在映射 [Required][ForeignKey] 中将其指定为不可为空,这就是 EF 混淆的原因。
标签: c# entity-framework sqlite