问题
I work on a project with Entity Framework Code First + Durandal + Breeze.
I have these entities models:
public class Packing
{
[Key]
public int Id { get; set; }
public string PackingDescription { get; set; }
...
public virtual List<Isotope> Isotopes { get; set; }
public virtual List<PhysicalForm> PhysicalForms { get; set; }
public virtual List<ChemicalForm> ChemicalForms { get; set; }
}
public class Isotope
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
...
public int PackingId { get; set; }
public virtual Packing Packing { get; set; }
}
public class ChemicalForm
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
...
public int PackingId { get; set; }
public virtual Packing Packing { get; set; }
}
public class PhysicalForm
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
...
public int PackingId { get; set; }
public virtual Packing Packing { get; set; }
}
When I run my project my Entity Framework Code First database is created.
First, I test the cascade delete 'by hand' directly in my database. When I have one Packing with multiple Isotopes and I delete the Packing, all cascaded Isotopes are deleted. This is ok for me.
Now at runtime in my project using breeze, when I try the same scenario: delete a Packing
element like this:
var deletePackings = function (packingsObservable) {
// Input: packingsObservable: an observable filled with a list of packings to delete
// Output: none
for (var i = 0; i < packingsObservable().length; i++) {
packingsObservable()[i].entityAspect.setDeleted();
};
return manager.saveChanges();
};
I got the error below:
The UPDATE statement conflicted with the FOREIGN KEY constraint \"FK_dbo.Isotopes_dbo.Packings_PackingId\". The conflict occurred in database \"TRANSPORTBOEKDB\", table \"dbo.Packings\", column 'Id'.\r\nThe statement has been terminated."}
Now I read on another SO post that
Breeze does not yet support client side 'cascaded' deletes (we are considering this one), you will need to iterate over any client side orders that are already loaded and 'detach' them.
So is this the reason why I got the error in my application?
Do I have to iterate over any child entities that are already loaded and 'detach' them?
UPDATE
By manually detaching any child entities by code with breeze do the trick but this is painful:
var deletePackings = function (packingsObservable) {
// Input: packingsObservable: an observable filled with a list of packings to delete
// Output: none
// Remark: we loop from end to begin of the observable!
var entity;
// Since Breeze does not yet support client side 'cascaded' deletes (we are considering this one),
// you will need to iterate over any child entity that are already loaded and 'detach' them.
for (var i = packingsObservable().length - 1; i >= 0; i--) {
// Detach any child entities of type isotope
for (var j = packingsObservable()[i].isotopes().length - 1; j >= 0; j--) {
entity = packingsObservable()[i].isotopes()[j];
manager.detachEntity(entity);
}
// Detach any child entities of type chemicalForm
for (var j = packingsObservable()[i].chemicalForms().length - 1; j >= 0; j--) {
entity = packingsObservable()[i].chemicalForms()[j];
manager.detachEntity(entity);
}
// Detach any child entities of type physicalForm
for (var j = packingsObservable()[i].physicalForms().length - 1; j >= 0; j--) {
entity = packingsObservable()[i].physicalForms()[j];
manager.detachEntity(entity);
}
packingsObservable()[i].entityAspect.setDeleted();
};
return manager.saveChanges();
};
No better solution?
回答1:
Do cascade delete in SQL if needed and forget in on client, just refresh data after.
Or you can add new IsActive column for agreggate entity, this is my prefered approach, I am scared of DB deletes:)
回答2:
Support for cascade delete is a very reasonable request.
Please add a vote for client side cascade delete support here: Breeze User Voice. We take this venue very seriously in determining what features to add to the Breeze product.
回答3:
The feature the breeze authors are considering is client-side cascade delete, but breeze also has no support for the server-side cascade delete. You have to do certain things in order to use a server-side cascade delete.
setDeleted nulls all referencing fkey values in the cache -- even if the fkey is non-nullable. If a referencing record has a non-nullable fkey constraint, then you need to prevent saving the child records since the UPDATE would fail. You're approach to evict the children from the cache before the save accomplishes this goal and allows you to call saveChanges() with no parameters. Alternatively, you can pass an array that contains the records you set deleted. You would then probably want to evict the children after the save. Or you can just stop using that entity manager.
来源:https://stackoverflow.com/questions/16221693/error-with-breeze-when-deleting-an-entity-which-contains-child-entities