我有一个名为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更改为“Detached”,如果我删除了服务器上也存在的设备,则其entityState将更改为“Deleted”。我不能比这更进一步,我希望有人可以解释为什么会发生这种情况?
答案 0 :(得分:4)
为了清楚起见,通过entityAspect.setDeleted删除实体会导致其entityState设置为“Deleted”。此操作在下次保存时标记要删除的实体,并将其从客户端上的任何导航集合中删除。在此操作之后,EntityManager仍在跟踪实体。
相反,通过entityAspect.setDetached分离实体将其从entityManager缓存中完全删除。这也会从客户端上的任何导航集合中删除实体,但在EntityManager.saveChanges调用期间对服务器没有影响,因为EntityManager不再“知道”该实体。将“分离”想象为告诉EntityManager完全忘记一个实体,就好像它从来没有被查询过一样。
“删除”一个实体,然后“重新添加”同一个实体是有问题的,因为这会导致EntityManager有两个相同实体的化身;删除的版本和添加的版本。因此,EntityManager会抛出您看到的异常。
我认为您要做的是删除并添加具有不同ID的“新”克隆实体。
希望这是有道理的!
答案 1 :(得分:2)
发生这种情况的原因是Breeze跟踪该实体,直到您完全从服务器中删除它,以防止您创建具有相同ID的新实体,这当然会引发服务器异常,因为您可以'那样做。
如果在尝试重新创建它之前在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的新实体