【发布时间】:2014-02-15 23:20:44
【问题描述】:
我遇到了一个反复出现但毫无意义的问题,希望有人(在 Breeze 团队中?)能解释一下。
以下模型说明了相关实体。
如您所见,我在属性名称中非常严格地遵守实体框架约定,因此,如果我在 SQL 中签入,删除规则的级联是由 EF 代码在创建数据库时首先设置的。
现在,当我尝试在 SQL 中手动删除 BusUnit 时,删除级联正确,并且相应的 BusUnitDimensions 也被删除,应该是这样。同样,如果我在 SQL 中删除了一个Dimension,相应的BusUnitDimensions 也会被删除。
但是,在我的应用程序中,如果我使用 Breeze 将 BusUnit 标记为 setDeleted,然后尝试 saveChanges,则会收到以下错误。
The operation failed: The relationship could not be changed because one
or more of the foreign-key properties is non-nullable. When a change is
made to a relationship, the related foreign-key property is set to a null
value. If the foreign-key does not support null values, a new relationship
must be defined, the foreign-key property must be assigned another
non-null value, or the unrelated object must be deleted.
但奇怪的是,如果我将 Dimension 标记为删除然后保存(在 Breeze 中),级联删除工作正常,Dimension 及其对应的 BusUnitDimensions 都被删除。
那么,为什么不一致?为什么 SQL 中的级联删除规则不适用于BusUnits,但它们却适用于Dimensions?我在其他地方读到 Breeze 不支持级联删除,但是为什么我的 Dimensions 案例有效?
编辑:
我已经删除了我之前的编辑,因为它们不相关。以下更改来自 Ward 的回答...
我的模型现在看起来像这样,BusUnitDims 现在使用BusUnitId 和DimId 作为复合键,并且我添加了bool、IsBud 用于有效负载。
我还没有为 BusUnits 实现删除,但是如果我尝试删除 Dim,我会收到相同的错误消息:
The operation failed: The relationship could not be changed because one
or more of the foreign-key properties is non-nullable. When a change is
made to a relationship, the related foreign-key property is set to a null
value. If the foreign-key does not support null values, a new relationship
must be defined, the foreign-key property must be assigned another
non-null value, or the unrelated object must be deleted.
我注意到级联删除不再启用,实际上,为了让 EF 构建数据库,我添加了以下配置:
modelBuilder.Entity<BusUnitDim>()
.HasRequired(bud => bud.BusUnit)
.WithMany(bu => bu.BusUnitDims)
.HasForeignKey(bud => bud.BusUnitId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<BusUnitDim>()
.HasRequired(bud => bud.Dim)
.WithMany(d => d.BusUnitDims)
.HasForeignKey(bud => bud.DimId)
.WillCascadeOnDelete(false);
因此,现在明显没有级联,我可以理解为什么会发生错误。这是否意味着在控制器中,必须在删除父 Dim 或 BusUnit 时以及在调用 saveChanges 之前专门标记要删除的每个映射,或者是否有某种方法可以配置 EF 以利用级联删除,因为这将极大地简化我的控制器中的代码?
(PS:它变得更加复杂,因为BusUnitDims 最终有一个自己的连接表,MetricBusUnitDims 以容纳模型中的另一个实体及其关系。这就是我试图尽早掌握原则)
编辑:(BUSUNITS 控制器解决方案)
因此,以下方法适用于BusUnits:
function deleteBusUnit(busUnitVm) { // note that you pass in the item viewmodel, not the entity
var busUnit = busUnitVm.busUnit;
var mapVms = busUnitVm.dimMapVms;
var dimHash = createBusUnitDimHash(busUnit);
mapVms.forEach(function (mapVm) {
var map = dimHash[mapVm.dim.id];
if (map) {
datacontext.markDeleted(map);
}
});
datacontext.markDeleted(busUnit);
save().then(function() { getDBoardConfig(); });
}
}
这是正确的方法吗?如果是这样,我仍然需要弄清楚以下内容:
- 如何联系
Dims。这些是不同的,因为项目视图模型是为 BusUnits 定义的。 - 如何处理存在下一级连接表的情况,例如
MetricBusUnitDIm。
编辑:(DIMS 的控制器解决方案)
function deleteDim(dim) {
return bsDialog.deleteDialog(dim.name, true)
.then(function () {
vm.busUnitVms.forEach(function (busUnitVm) {
busUnitVm.busUnit.busUnitDims.forEach(function (bud) {
if (bud.dimId === dim.id) {
datacontext.markDeleted(bud);
}
});
});
datacontext.markDeleted(dim);
save().then(function () { getDboardConfig(); });
});
}
【问题讨论】:
-
通常避免专门向用户寻求帮助 - 只是考虑负载,但如果您正在寻求个人的特定支持,您是否考虑过付费支持?
-
@PWKad 谢谢。对 SO 来说相对较新,如果我违反了不成文的礼仪,请道歉。我目前正在与有关公司进行讨论,但我们的时差使势头变慢。
标签: entity-framework breeze cascading-deletes