1

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

在我的模型中,我有两个对象ObjectAObjectB都继承自BaseObject,显然每个对象都有自己的附加属性。

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

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

问题是它永远不会正确保存,但根据我采用的方法,我会得到不同的结果。因此,因为用户可以中止新的对象进程,所以我正在创建ChildObjectsEntityState.Detached因为我认为如果它们被丢弃会更容易。我意识到,尽管以这种方式创建的所有实体都获得了 id 键 0。所以我在将ChildEntites添加到父级(ObjectAObjectB)时修复了这些键,方法是为它们分配递减的负数(即:-1 、-2 等)。这导致了一些疯狂的服务器端行为,只有一些实体被保存到数据库和外键冲突的投诉。

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

我仍然认为我还没有完全正确地理解如何处理这个问题,所以一些指针将不胜感激。


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

4

1 回答 1

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

基本上以这种方式我们是 -

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

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

于 2013-06-19T13:22:29.740 回答