删除包含子实体的实体时出现breeze错误

时间:2013-04-25 18:06:57

标签: breeze

我使用Entity Framework Code First + Durandal + Breeze开展项目。

我有这些实体模型:

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; }
}

当我运行我的项目时,我的实体框架代码优先数据库已经创建。

首先,我直接在我的数据库中测试级联删除'手动'。当我有一个包含多个同位素的包装并删除包装时,所有级联的同位素都将被删除。这对我来说没问题。

现在在我的项目运行时使用breeze,当我尝试相同的场景时:删除这样的Packing元素:

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();
};

我收到了以下错误:

  

UPDATE语句与FOREIGN KEY约束“FK_dbo.Isotopes_dbo.Packings_PackingId”冲突。冲突发生在数据库\“TRANSPORTBOEKDB \”,表\“dbo.Packings \”,列'Id'。\ r \ n语句已终止。“}

现在我读了另一个SO post那个

  

Breeze尚不支持客户端“级联”删除(我们正在考虑这个),您需要迭代已加载的任何客户端订单并“分离”它们。

这就是我在申请中收到错误的原因吗?

我是否必须遍历已加载的任何子实体并“分离”它们?


更新

通过代码用微风手动分离任何子实体可以解决问题,但这很痛苦:

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();
};

没有更好的解决方案?

3 个答案:

答案 0 :(得分:2)

如果需要,在SQL中进行级联删除,忘记在客户端,只需刷新数据。

或者你可以为agreggate实体添加新的IsActive列,这是我最喜欢的方法,我害怕DB删除:)

答案 1 :(得分:1)

支持级联删除是一个非常合理的请求。

请在此处添加对客户端级联删除支持的投票:Breeze User Voice。我们非常重视这个场所,以确定添加到Breeze产品的功能。

答案 2 :(得分:1)

微风作者正在考虑的功能是客户端级联删除,但微风也不支持服务器端级联删除。您必须执行某些操作才能使用服务器端级联删除。

setDeleted使所有引用缓存中的fkey值都为空 - 即使fkey不可为空。如果引用记录具有不可为空的fkey约束,则需要阻止保存子记录,因为UPDATE将失败。在保存完成此目标之前,您可以从缓存中驱逐子级,并允许您在没有参数的情况下调用saveChanges()。或者,您可以传递包含已设置已删除记录的数组。那么你可能想要在保存后驱逐孩子们。或者您可以停止使用该实体管理器。