如何首先使用实体​​框架5代码删除具有导航属性的对象?

Ale*_* G. 6 code-first delete-row entity-framework-5

我首先使用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; }
}
Run Code Online (Sandbox Code Playgroud)

使用ApplicationPermission的以下映射:

HasKey(x => x.Id);
HasRequired(x => x.Application).WithMany().Map(m => m.MapKey("ApplicationId")).WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)

和申请:

HasKey(x => x.Id);
Run Code Online (Sandbox Code Playgroud)

我使用下面的代码删除ApplicationPermission:

ApplicationPermission entity = new ApplicationPermission { Id = id };
DbContext.Set<ApplicationPermission>().Attach(entity);
DbContext.Set<ApplicationPermission>().Remove(entity);
DbContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

但我在SaveChanges方法上遇到错误:

'CodeFirstContainer.ApplicationPermissions'中的实体参与'ApplicationPermission_Application'关系.找到0个相关的'ApplicationPermission_Application_Target'.1'ApplicationPermission_Application_Target'是预期的.

如何在不将Application加载到dbcontext的情况下删除ApplicationPermission?

Sla*_*uma 3

我相信,当您使用独立关联时,如果没有设置所需的导航属性,则无法删除实体。您必须从数据库加载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();
Run Code Online (Sandbox Code Playgroud)

调用时生成的SQL命令SaveChanges是:

exec sp_executesql N'delete [dbo].[ApplicationPermissions]
where (([Id] = @0) and ([ApplicationId] = @1))',N'@0 int,@1 int',@0=1,@1=5
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,对 的查询delete不仅要求删除IdApplicationPermission,还and要求 () 的外键值ApplicationId。为了成功,您必须知道并通过设置具有相同主键的相关实体来设置此 FK 值。

使用外键关联时不会出现该问题:

public class ApplicationPermission
{
    public virtual Application Application { get; set; }
    public int ApplicationId { get; set; }

    public int Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

映射:

modelBuilder.Entity<ApplicationPermission>()
    .HasRequired(x => x.Application)
    .WithMany()
    .HasForeignKey(x => x.ApplicationId)
    .WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用原始代码,而无需将 FK 属性设置ApplicationId为正确的值(默认为0那时),并且无需设置导航属性,删除实体即可。SQL命令不关心FK,只查询要Id删除ApplicationPermission的:

exec sp_executesql N'delete [dbo].[ApplicationPermissions]
where ([Id] = @0)',N'@0 int',@0=1
Run Code Online (Sandbox Code Playgroud)

我不知道为什么两种类型的关联之间的 SQL 命令不同。