如何首先使用实体框架 5 代码删除具有导航属性的对象?
Posted
技术标签:
【中文标题】如何首先使用实体框架 5 代码删除具有导航属性的对象?【英文标题】:How can I delete an object with navigation property with entity framework 5 code first? 【发布时间】:2012-10-15 18:00:21 【问题描述】:我首先使用的是 EF 5 代码,并且我有 2 个相关实体 ApplicationPermission 和 Application:
public class ApplicationPermission
public virtual Application Application get; set;
public int Id get; set;
public class Application
public string Name get; set;
public int Id get; set;
使用以下 ApplicationPermission 映射:
HasKey(x => x.Id);
HasRequired(x => x.Application).WithMany().Map(m => m.MapKey("ApplicationId")).WillCascadeOnDelete(false);
应用:
HasKey(x => x.Id);
我使用下面的代码来删除 ApplicationPermission:
ApplicationPermission entity = new ApplicationPermission Id = id ;
DbContext.Set<ApplicationPermission>().Attach(entity);
DbContext.Set<ApplicationPermission>().Remove(entity);
DbContext.SaveChanges();
但我在 SaveChanges 方法上遇到错误:
“CodeFirstContainer.ApplicationPermissions”中的实体参与 'ApplicationPermission_Application' 关系。 0 相关 找到了“ApplicationPermission_Application_Target”。 1 应为“ApplicationPermission_Application_Target”。
如何在不将 Application 加载到 dbcontext 的情况下删除 ApplicationPermission?
【问题讨论】:
【参考方案1】:我相信,当您使用独立关联时,如果没有设置所需的导航属性,就不可能删除实体。您必须从数据库中加载 Application
或 - 至少 - 知道外键值并使用该值附加一个 Application
实体,如下所示:
ApplicationPermission entity = new ApplicationPermission Id = 1 ;
entity.Application = new Application Id = 5 ;
DbContext.Set<ApplicationPermission>().Attach(entity); //attaches Application too
DbContext.Set<ApplicationPermission>().Remove(entity);
DbContext.SaveChanges();
调用SaveChanges
时生成的SQL命令为:
exec sp_executesql N'delete [dbo].[ApplicationPermissions]
where (([Id] = @0) and ([ApplicationId] = @1))',N'@0 int,@1 int',@0=1,@1=5
如您所见,delete
的查询不仅要求删除 ApplicationPermission
的 Id
,还要求删除 (and
) ApplicationId
的外键值。为了成功,您必须通过使用相同的主键设置相关实体来了解并设置此 FK 值。
使用外键关联时不会出现问题:
public class ApplicationPermission
public virtual Application Application get; set;
public int ApplicationId get; set;
public int Id get; set;
映射:
modelBuilder.Entity<ApplicationPermission>()
.HasRequired(x => x.Application)
.WithMany()
.HasForeignKey(x => x.ApplicationId)
.WillCascadeOnDelete(false);
然后您可以使用您的原始代码,而无需将 FK 属性 ApplicationId
设置为正确的值(然后将默认为 0
)并且无需设置导航属性并且删除实体将起作用。 SQL 命令不关心 FK,只查询要删除的 ApplicationPermission
的 Id
:
exec sp_executesql N'delete [dbo].[ApplicationPermissions]
where ([Id] = @0)',N'@0 int',@0=1
我不知道为什么两种关联类型的 SQL 命令不同。
【讨论】:
以上是关于如何首先使用实体框架 5 代码删除具有导航属性的对象?的主要内容,如果未能解决你的问题,请参考以下文章
首先是实体框架代码。如何将对象类型文件的列表添加到已具有该类型属性的对象