2012-03-08 74 views
1

我有下面的模型。删除实体框架中的多对多关系会引发错误

enter image description here

我试图删除与ActivityType相关的给定productType;但是,当我试图通过我的泛型方法发起删除操作时,它不仅删除了关系,而且试图删除ProductType!在where子句中导致erorr的主键为零

“存储更新,插入或删除语句影响了意外数量的行(0)。实体可能在实体加载后被修改或删除。 ObjectStateManager条目“。

要在下面删除的代码;

public void DeleteEntityAndSaveChanges<T, T1>(T entity, List<T1> subEntities) 
      where T : class 
      where T1 : class 
     { 
      Set<T>().Attach(entity); 
      DeleteEntitiesAndSaveChanges(subEntities); 
     } 

public void DeleteEntitiesAndSaveChanges<T>(List<T> entities) where T : class 
     { 
      foreach (var entity in entities) 
      { 
       Set<T>().Attach(entity); 
       Set<T>().Remove(entity); 
      } 

      SaveChanges(); 
     } 

用法:

DbContext.DeleteEntityAndSaveChanges(request.ActivityType, request.ActivityType.ProductTypes); 

这是所生成的SQL这就是:

exec sp_executesql N'delete [dbo].[ProductTypeActivityTypes] 
where (([ProductType_ProductTypeId] = @0) and ([ActivityType_EntityObjectId] = @1))',N'@0 bigint,@1 bigint',@0=1,@1=20 

这是有问题的SQL是不想送出,但被由EF生成:

EXEC sp_executesql的N'delete [DBO]。[ProductTypes] 其中(([ProductTypeId] = @ 0)和[时间戳]为null)”,N '@ 0 BIGINT',@ 0 = 1

关于如何才能让它只能删除关系的任何想法?

干杯。

回答

3

当您在DbSet上调用Remove时,这意味着在调用SaveChanges时从数据库中删除该实体。据我了解,你真正想要做的是去除两个实体之间的关联。一般来说,您可以通过从其他实体的集合导航属性中删除一个实体来完成此操作。例如:

product.Activities.Remove(activity); 

但是这里有一个皱纹。在您的示例代码中,您正在调用Attach将两种类型的实体附加到上下文中。呼叫附加不会设置或恢复实体之间的任何关系。这是因为,对于多对多关系而言,实体中没有FK提供有关它与其他实体相关的信息。 FK由连接表来处理,它不会在EF多对多映射中公开。

有几种方法可以解决这个问题。首先,如果可能且对您的体系结构合理,则可以让EF上下文跟踪实体从查询到查询SaveChanges的时间。这样EF将跟踪您的关系,包括跟踪删除。其次,如果需要将实体附加到新的上下文中,那么您需要跟踪这些关系,以便可以恢复这些关系。有几种方法可以恢复关系。一种方法是在调用Attach之前构建相关实体的图形。当调用Attach时,EF将遍历并附加整个图形,包括关系。例如:

// Restore the graph 
product.Activities.Add(activity1); 
product.Activities.Add(activity2); 
context.Products.Attach(product); 

// Delete the relationship 
product.Activities.Remove(activity1); 
context.SaveChanges(); 

(我不使用你的泛型方法只是为了让代码更清楚一点它应该工作与仿制药相同的方式。)