C# 实体框架删除问题(使用wpf)

C# 实体框架删除问题(使用wpf),c#,wpf,entity-framework,C#,Wpf,Entity Framework,我有以下问题。我有典型的主/细节UI场景。我将主对象(CommissionPlan)设置为DataContext。然后我将网格绑定到CommissionPlanItems(这是子项的集合) 添加/更新时一切都很好。当我尝试删除现有行时-我得到以下EF错误: 无法更改关系,因为一个或多个外键属性不可为null。对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象 我找到了很多关于如何处理这件事的收据。但我不知道在

我有以下问题。我有典型的主/细节UI场景。我将主对象(CommissionPlan)设置为DataContext。然后我将网格绑定到CommissionPlanItems(这是子项的集合)

添加/更新时一切都很好。当我尝试删除现有行时-我得到以下EF错误: 无法更改关系,因为一个或多个外键属性不可为null。对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象


我找到了很多关于如何处理这件事的收据。但我不知道在我的情况下该怎么做,因为删除是自动神奇地发生的,通过从网格中删除行。在这种情况下,我应该修改什么?

问题是WPF网格仅从CommissionPlan.CommissionPlanItems集合中删除项。在常见场景中,这并不意味着将删除数据库中的项。仅删除项目之间的关系,并且CommissionPlanItem的CommissionPlanId将设置为null。如果不可为null,则将获得异常


解决方案是在
ObjectContext
中删除已删除的项,或者修改实体模型以支持(我认为只有在实体框架4中才可能)。我会把它标记为一个答案,但如果有人能给我更好的方法,我将不胜感激。基本上,我正在检查ObjectStateManager是否有修改过的实体(有更好的方法查看这些实体吗?),然后如果我看到修改涉及将parent设置为“null”-我知道该实体已从我的图中“分离”,我会继续删除它

modified = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
                if (modified != null && modified.Count() > 0)
                {
                    foreach (ObjectStateEntry ose in modified)
                    {
                        if (
                            (ose.Entity.GetType() == typeof(CommissionPlanCustomer) && ((CommissionPlanCustomer)ose.Entity).CommissionPlan == null)
                            ||
                            (ose.Entity.GetType() == typeof(CommissionPlanItemEligibleUser) && ((CommissionPlanItemEligibleUser)ose.Entity).CommissionPlanItem == null)
                            ||
                            (ose.Entity.GetType() == typeof(CommissionPlanItem) && ((CommissionPlanItem)ose.Entity).CommissionPlan == null)
                           )
                        {
                            context.DeleteObject(ose.Entity);
                        }
                    }
                }

这里还有另一个建议:您可以修改实体模型以支持标识关系,而无需更改数据库设计。然后在XML编辑器中打开edmx文件,并将引用字段添加到关键字段。在这种情况下,它看起来像:

<edmx:StorageModels>
<Schema ...>
  ...
  <EntityType Name="CommissionPlanItems">
    <Key>
       <PropertyRef Name="CommissionPlanItemsId" />
       <PropertyRef Name="CommissionPlanId" /> <!-- This line added -->
    </Key>
  ...
  </Schema>
</edmx:StorageModels>
<edmx:ConceptualModels>
  <Schema ...>
      ...
     <EntityType Name="CommissionPlanItems">
        <Key>
          <PropertyRef Name="CommissionPlanItemsId" />
          <PropertyRef Name="CommissionPlanId" /> <!-- This line added -->
        </Key>
      ...
  </Schema>
</edmx:ConceptualModels>

...
...
...
...

我已经尝试过了,现在可以使用datagrid来插入、删除和更新细节项。它可能需要进一步测试。如果运行“从数据库更新模型”,则可能需要再次编辑edmx文件。

还可以连接AssociationChanged事件,以检测DataGrid何时删除了EF关系。如果在实体上调用DeleteObject。朱莉·勒曼(Julie Lerman)在题为“使用实体框架和WPF拖放数据绑定”的文章中提供了完整的解释。她随附的视频很好地解释了这项技术(将视频提前到25分钟)。

Ladislav,我想我现在明白了。从数据库设计的角度来看,修改以支持标识关系似乎不是一个好主意。这个复合键的东西正常吗?!如何从ObjectContext中删除对象?我应该在保存更改之前搜索它们并执行此操作吗?你们有样品吗?就像我说的,我无法控制它是如何完成的,因为grid做到了。我可能需要在网格之后去“清理”。@katit:我也不喜欢识别关系的想法,但这是它在EF中的工作方式。我不是WPF开发人员,所以我通常不知道如何处理它。它通常在
observateCollection
上执行,您可以在这里处理
CollectionChanged
之类的事件。因此,您可能应该将CommissionPlanItems包装到ObservableCollection中并处理事件。这是一个最大的问题。我不想在更新时反转模式