3

我有一个名为 DeviceAccount 的模型。这是一个连接表,允许我创建多对多关系。

我有一个功能,它通过将一个帐户和一个设备交给它来创建一个新的 DeviceAccount 加入。看这里:

var createDeviceAccount = function (account, device) {
        var initialValues = {
            account: account,
            device: device
        };
        return manager.createEntity(entityNames.deviceAccount, initialValues);
    };

我有一个删除 DeviceAccount 的功能。看这里:

var deleteDeviceAccount = function (account, device) {
        var baseQuery = entityQuery.from('DeviceAccounts');
        var p1 = new breeze.Predicate('device', 'eq', device);
        var p2 = new breeze.Predicate("account", "eq", account);
        var modQuery = baseQuery.where(p1.and(p2));
        var results = manager.executeQueryLocally(modQuery);
        results[0].entityAspect.setDeleted();
    };

如果我在本地创建、删除、创建、删除相同的设备/帐户对,则没有问题。如果我使用服务器上存在的设备/帐户对,我可以很好地删除它,但是当我再次添加它时,我收到以下错误:

未捕获的错误:此密钥已附加:DeviceAccount:#Test.Models-5:::5

如果我更深入地遵循这一点,我可以看到删除本地设备会将 entityState 更改为“已分离”,如果删除服务器上也存在的设备,则其 entityState 将更改为“已删除”。我不能比这更进一步,我希望有人能解释为什么会发生这种情况?

4

2 回答 2

4

为了清楚起见,通过 entityAspect.setDeleted删除实体会导致其 entityState 设置为“已删除”。此操作将实体标记为在下次保存时删除,并将其从客户端上的任何导航集合中删除。在此操作之后,EntityManager 仍在跟踪实体。

相反,通过 entityAspect.setDetached分离实体会将其从 entityManager 缓存中完全删除。这也会从客户端上的任何导航集合中删除实体,但在 EntityManager.saveChanges 调用期间对服务器没有任何影响,因为 EntityManager 不再“知道”实体。将“分离”想象成告诉 EntityManager 完全忘记一个实体,就好像它一开始就没有被查询过。

“删除”一个实体然后“重新添加”同一个实体是有问题的,因为这会导致 EntityManager 具有同一个实体的两个化身;删除的版本和添加的版本。因此,EntityManager 会引发您所看到的异常。

我认为您想要做的是删除并添加一个具有不同 ID 的“新”克隆实体。

希望这是有道理的!

于 2013-10-15T17:21:39.967 回答
2

发生这种情况的原因是 Breeze 一直在跟踪该实体,直到您将其从服务器中完全删除,以防止您创建具有相同 ID 的新实体,这当然会引发服务器异常,因为您不能这样做.

如果您在尝试重新创建 entityManager 之前在 entityManager 上调用了 saveChanges(),那么 Breeze 将前往服务器,从数据库中删除实体,返回承诺,并从本地缓存中完全分离实体,因为它不再存在在服务器上。

您可以手动将 entityState 设置为分离,但是如果您尝试 saveChanges 并且该 ID 已存在于服务器上,则会引发错误。

最佳选择

将实体传递给数组中的 saveChanges 方法 -

results[0].entityAspect.setDeleted();
manager.saveChanges([results[0]]).then(saveSucceeded);

function saveSucceeded() {
    console.log('Entity removed from server');
}

现在 saveSucceeded 完成后,您可以使用该 ID 创建一个新实体

于 2013-10-15T16:39:58.080 回答