处理可能被丢弃的新微风实体的正确方法是什么?

时间:2013-06-19 09:30:11

标签: breeze

我确信我已经在这里创造了自己的痛苦,但我很难理解在我的场景中管理创建新实体的正确事件顺序。

在我的模型中,我有两个对象, ObjectA ObjectB ,它们都继承自 BaseObject ,显然每个对象都有自己的附加属性。< / p>

在我看来,由于大多数信息是相同的,我希望用户能够选择一个选项来创建哪一个。因此,他们填写 SharedProperty1 SharedProperty2(这是一个集合导航属性),选择一个关于他们是否需要A或B对象的选项,然后填写最终版本具有最后一个对象特定属性的页面。

由于我不知道在用户选择此选项之前要创建哪个实体,因此我在viewmodel中构建了一个对象来处理此临时数据。作为其中一部分,当他们填写 SharedProperty2(集合)时,当他们添加新的 ChildObjects 时,我使用entityManager.createEntity('ChildObject')创建它们。然后,当他们到达最后,我创建 ObjectA ObjectB 实体并添加子权限(和其他属性),然后尝试保存。

问题是它永远无法正确保存,但根据我采用的方法,我会得到不同的结果。因为用户可以直接中止新的对象进程,我使用EntityState.Detached创建了 ChildObjects ,因为我认为如果它们被扔掉会更容易。我意识到以这种方式创建的所有实体都获得了id键0.所以我在将 ChildEntites 添加到父级( ObjectA 或者 ObjectB ),通过为它们分配减少的负数(即:-1,-2等)。这导致了一些疯狂的服务器端行为,只有一些实体被保存到数据库并且抱怨冲突的外键。

这也有一种难闻的气味,我没有正确理解这一点,而且我弄得一团糟。所以现在我尝试正常创建实体(即:没有Detached标志),并且它们都获得了自己的唯一键(再次微风似乎跟随-1,-2等),但现在当我尝试要将它们从我的临时viewmodel集合复制到父对象集合,我收到an entity with this key is already attached的错误。所以现在我甚至无法建立正确的模型来保存。

我仍然认为我没有完全理解如何处理这个问题,因此我们会非常感激一些指示。


为了避开我怀疑会成为问题的问题,为什么我没有使用RejectChanges来处理被丢弃的实体。基本上用户可以添加一个ChildObject(对象由breeze entityManager创建,添加到viewmodel集合,绑定到UI),然后决定在保存数据之前再次删除它(目前只是从viewmodel集合中删除)。如果我使用拒绝改变,我会抛弃其他重要的诱惑。我想如果有人在视图中删除了ChildObject,我现在将成为一个好孩子并使用正确的分离方法。

1 个答案:

答案 0 :(得分:2)

如果我正确理解了您的问题,那么您正在尝试创建一些属性,然后在保存时将它们添加到父对象集合中。如果我错了,请纠正我,但Breeze不仅支持这一点,而且非常有效地非常。来自.NET和C#,我很难理解这是多么容易,但如果我是你,我会这样做 -

var childA = ko.observable();
var childB = ko.observable();

childA(entityManager.createEntity('ChildObject')); // populate your children
childB(entityManager.createEntity('ChildObject')); // populate your children

然后您可以在视图中编辑它们,当您准备好保存时,只需将它们添加到集合中。

var save = function() {
    isSaving(true);
    var parent = ko.observable();
    return entityManager.getParent(parent, parentId)
            .then(setParents)
            .fail(catchError);

    function setParents() {
        childA().parent(parent());
        childB().parent(parent());
        entityManager.saveChanges()
                .then(complete)
                .fail(catchError);

        function complete() {
            isSaving(false);
            return Q.resolve();  // Don't know if you have any unresolved conflicts
        }
    }  
};

基本上我们就是这样 -

答:创建实体 B:编辑它们而不执行任何更改 C:当我们调用save时,我们正在设置他们的父导航属性。在我以前的方式(无论是对还是错)我只需设置ParentId(parentId)并让EF弄清楚如何导航但是(原谅双关语)这对Breeze来说是轻而易举的。我们也可以轻松地传递父观察,而不必从经理那里得到它,这取决于我们是否已经拥有它。

如果要单独管理实体,另一种方法是在实体中使用entityManager.saveChanges([childA])一次保存单个实体。只需传入一个包含要保存的单个实体的数组。如果您正在处理多个实体但这些实体尚未准备好保存并且您需要浏览应用程序,这可能很有用。除非你调用cancelChanges(),否则Breeze会将实体保留在缓存中,直到你准备再次使用它为止。通过这种方式,只需调用处于isAdded()状态的实体,您就可以重新启动并重新编辑。