Breeze 增加了实体don';t在entityManager.saveChanges()之后更改entityState
我在EntityManager中创建了一个新实体,如下所示:Breeze 增加了实体don';t在entityManager.saveChanges()之后更改entityState,breeze,entitymanager,Breeze,Entitymanager,我在EntityManager中创建了一个新实体,如下所示: var newCust = manager.createEntity('Customer', { Name: 'MyNewCustomer' }); 它的Id已正确生成。在按钮上单击“我将实体保存在服务器上”: manager.saveChanges([newCust]).then(function (saveResult) { alert('saved!'); } 现在一切都很完美,但newCust中的实体保持其Entity
var newCust = manager.createEntity('Customer', { Name: 'MyNewCustomer' });
它的Id已正确生成。在按钮上单击“我将实体保存在服务器上”:
manager.saveChanges([newCust]).then(function (saveResult) {
alert('saved!');
}
现在一切都很完美,但newCust中的实体保持其EntityState“已添加”。它不会变为“不变”
我调试了一下,发现在breeze的函数“mergeEntity(mc,node,meta)”中,出现了以下代码-没有找到任何实体(即使它搜索的键是相同的Id-Id修复程序工作正常):
因此,每次保存新实体时,都会在EntityManager中创建一个新实体。当我重新加载页面时,实体被正确标记并工作。唯一的问题是,每次保存更改时都会保存一个新实体
谢谢你的帮助
编辑1:
我发现了这个问题,我不确定Breeze对我的期望是什么。当我的ContextProvider保存实体时,它会发送一个DB Update命令(用于所有属性),然后返回。问题是,saveResult对象的Id仍然是“tempId”,而不是真实的Id——因此,当客户端的Breeze接收到该对象时,它在entityManager中再也找不到它了,因为密钥修复已经发生了
Breeze希望从saveResult中得到什么?此时对象在数据库中的表示形式?-这是有道理的,但我没有发现它的文件
编辑2:
看起来我无法替换saveWorkState.saveMap中的对象(EntityInfo.Entity为只读)。我想做的是创建新添加的对象并返回此对象,而不是breeze发送给我的对象。我已经计算了新创建的对象和新的“real”Id的值。NoDB示例似乎只是覆盖新Id的Id,但任何其他属性都没有改变。也许我没有使用这个机制,对吗?为了确保SaveResult中返回的所有EntityInfos都是数据库的最新表示形式,我只需清除saveWorkState.SaveMap-list
saveWorkState.SaveMap[n].Clear()
并添加新的表示
saveWorkState.SaveMap[n].AddRange(newEntityInfos);
对于添加或修改的每个实体,我使用数据库返回的对象创建一个新的EntityInfo
private EntityInfo SaveEntity(List<KeyMapping> keyMap, EntityInfo info) {
EntityInfo result = info;
switch (info.EntityState) {
case EntityState.Added: {
// CreateInDatabase
// Possible changes in object properties happen (for calculated values)
...
var newObj = GetObjectAgainFromDatabase(info.Entity);
keyMap.Add(new KeyMapping() { EntityTypeName = bu.RuntimeClass.FullName, TempValue = (MyObject)info.Entity.Id, RealValue = newObj.Id });
result = CreateEntityInfo(newObj, EntityState.Added);
break;
}
case EntityState.Deleted: {
// Delete in Database
// EntityInfo doesn't have to change
break;
}
case EntityState.Modified: {
// Update in Database
result = CreateEntityInfo(bu.WrappedPOCO, EntityState.Modified);
break;
}
default: //EntityState.Detached, EntityState.Unchanged
break;
}
return result;
}
私有EntityInfo保存实体(列表键映射,EntityInfo){
EntityInfo结果=信息;
开关(信息实体状态){
案例实体状态。添加:{
//创建数据库
//对象特性可能发生更改(对于计算值)
...
var newObj=GetObjectAgainFromDatabase(info.Entity);
Add(new KeyMapping(){entitytytypename=bu.RuntimeClass.FullName,TempValue=(MyObject)info.Entity.Id,RealValue=newObj.Id});
结果=CreateEntityInfo(newObj,EntityState.Added);
打破
}
案例实体状态。已删除:{
//在数据库中删除
//EntityInfo不必更改
打破
}
案例实体状态。已修改:{
//数据库中的更新
结果=CreateEntityInfo(bu.WrappedPOCO,EntityState.Modified);
打破
}
默认值://EntityState.Detached,EntityState.Unchanged
打破
}
返回结果;
}
欢迎对此解决方案发表任何意见 实体的Id类型是什么?您是如何生成它的?它是一个GUID,在客户端临时生成,然后在服务器端生成“for real”。所以问题是:在SaveChangesCore中,我是否必须将saveWorkState中的实体与从数据库“获取”的对象的新版本交换?所以我必须从DB中查询每个对象?实际上,让Breeze管理“临时”和“真实”GUI合并的最简单方法是实现自己的Breeze KeyGenerator。看看这篇文章是否有用。
private EntityInfo SaveEntity(List<KeyMapping> keyMap, EntityInfo info) {
EntityInfo result = info;
switch (info.EntityState) {
case EntityState.Added: {
// CreateInDatabase
// Possible changes in object properties happen (for calculated values)
...
var newObj = GetObjectAgainFromDatabase(info.Entity);
keyMap.Add(new KeyMapping() { EntityTypeName = bu.RuntimeClass.FullName, TempValue = (MyObject)info.Entity.Id, RealValue = newObj.Id });
result = CreateEntityInfo(newObj, EntityState.Added);
break;
}
case EntityState.Deleted: {
// Delete in Database
// EntityInfo doesn't have to change
break;
}
case EntityState.Modified: {
// Update in Database
result = CreateEntityInfo(bu.WrappedPOCO, EntityState.Modified);
break;
}
default: //EntityState.Detached, EntityState.Unchanged
break;
}
return result;
}