Сблъсквам се с повтарящ се проблем, който просто няма смисъл, и се надявам, че някой (от екипа на Breeze?) може да хвърли малко светлина.
Следният модел илюстрира въпросните обекти.
Както можете да видите, аз се придържам доста стриктно към конвенциите на Entity Framework в моите имена на свойства и в резултат на това, ако проверя в SQL, правилата за каскада за изтриване се задават първо от EF кода, когато създава db.
Сега, когато се опитам да изтрия BusUnit
ръчно в SQL, каскадите за изтриване правилно и съответните BusUnitDimensions
също се изтриват, както трябва да бъде. По същия начин, ако изтрия Dimension
в SQL, съответните BusUnitDimensions
също се изтриват.
Въпреки това, в моето приложение, ако маркирам BusUnit
като setDeleted
с Breeze и след това опитам 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
работи?
РЕДАКТИРАНЕ:
Премахнах предишните си редакции, тъй като не бяха уместни. Промените по-долу следват отговора на Уорд...
Моят модел сега изглежда така и 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(); });
});
}