Breeze 删除然后添加新的相同实体会引发错误

Breeze 删除然后添加新的相同实体会引发错误,breeze,Breeze,我有一个叫做DeviceAccount的模型。它是一个连接表,允许我创建多对多关系 我有一个函数,通过给它一个帐户和一个要加入的设备来创建一个新的DeviceAccount。请看这里: var createDeviceAccount = function (account, device) { var initialValues = { account: account, device: device };

我有一个叫做DeviceAccount的模型。它是一个连接表,允许我创建多对多关系

我有一个函数,通过给它一个帐户和一个要加入的设备来创建一个新的DeviceAccount。请看这里:

var createDeviceAccount = function (account, device) {
        var initialValues = {
            account: account,
            device: device
        };
        return manager.createEntity(entityNames.deviceAccount, initialValues);
    };
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的函数。请看这里:

var createDeviceAccount = function (account, device) {
        var initialValues = {
            account: account,
            device: device
        };
        return manager.createEntity(entityNames.deviceAccount, initialValues);
    };
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();
    };
如果我在本地创建、删除、创建、删除相同的设备/帐户对,则没有问题。 如果我使用服务器上存在的设备/帐户对,我可以很好地将其删除,但当我再次添加时,我收到以下错误:

未捕获错误:此密钥已附加: 设备帐户:#测试。型号-5::5


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

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

如果在尝试重新创建entityManager之前调用了saveChanges(),那么Breeze将转到服务器,从DB中删除实体,返回承诺,并从本地缓存中完全分离该实体,因为该实体在服务器上已不存在

您可以手动将entityState设置为Distached,但是如果您尝试保存更改,并且服务器上已经存在该ID,则会抛出错误

最佳选择 将实体传递到数组中的saveChanges方法-

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

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

现在,在SaveSuccessed完成后,您可以使用该ID创建一个新实体,只需澄清,通过entityAspect.setDeleted删除一个实体会将其entityState设置为“已删除”。此操作将在下次保存时标记要删除的实体,并将其从客户端上的任何导航集合中删除。执行此操作后,EntityManager仍在跟踪该实体

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

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

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


希望这有意义

谢谢你的回答,但我还是有点困惑。。。好的,当我运行CreateDeviceAccount函数时,它应该创建一个具有唯一ID的全新实体,但由于某些原因,它假设旧实体的ID。我不知道为什么会这样?是因为Breeze中的某些东西检测到所有属性都与旧实体(标记为删除)匹配,因此不会创建新实体吗?只有定义为键的一部分的字段用于确定“唯一性”。实体创建代码是什么样子的?此entityType的元数据是什么样子的。谢谢!我发现了问题。我的主键是从帐户和设备属性生成的。将其更改为唯一生成属性修复了该问题。我确信问题出在javascript中,甚至没有想到检查数据库。@JayTraband-下面的场景有指导方针吗?在角度组件中,Breeze实体管理器跟踪更改,例如添加时的createEntity()。但是想象一下,如果他们从添加屏幕单击取消,现在转到另一个组件。好的,Breeze管理器仍然在跟踪createEntity,所以下次调用commit()时,它会尝试添加它!只有在用户刷新屏幕时才能解决此问题。有没有指导原则可以确保状态管理器在用户转到其他组件时忘记挂起的更改?感谢您的回答,我相信您的解决方案会起作用,但对我来说似乎并不理想。我不是在添加同一个实体,而是在添加一个新实体,它恰好具有相同的属性(id除外),但是当我尝试创建这个新实体时,它会得到与旧实体相同的id,并抛出此错误?。。。这意味着当我执行saveChanges时,我希望它删除旧实体,添加一个具有相同设备和帐户属性但具有新唯一ID的新实体。