7

我首先使用 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?

4

1 回答 1

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();

调用时生成的 SQL 命令SaveChanges则为:

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

如您所见,对 的查询不仅delete要求删除 的 ,还要求 ( ) 的外键值。为了成功,您必须通过使用相同的主键设置相关实体​​来了解并设置此 FK 值。IdApplicationPermissionandApplicationId

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

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为正确的值(默认为0then),并且无需设置导航属性并且删除实体将起作用。SQL 命令不关心 FK,只查询要删除Id的:ApplicationPermission

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

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

于 2012-10-15T19:31:02.820 回答