Breeze 增加了实体don';t在entityManager.saveChanges()之后更改entityState

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

我在EntityManager中创建了一个新实体,如下所示:

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