【问题标题】:Breeze is not storing the right value (that is set in code) when saving during entityChanged event在 entityChanged 事件期间保存时,Breeze 未存储正确的值(在代码中设置)
【发布时间】:2014-09-10 15:38:29
【问题描述】:

我有一个 Breeze、Typescript、MVC 5.2、Knockout、Entity Framework webapp。当用户单击网格(kogrid)中的一行时,我尝试更新用户实体的值。该值(应该)保存在 entityChanged 事件处理程序中,但在 Fiddler 中我看到属性值没有更改,并且 entityAspect.entityState 设置为 Modified(!) originalValuesMap 具有旧的 TenantId 并且是唯一的值地图。

我像这样订阅实体更改事件:

this.EntityManager.entityChanged.subscribe((data: breeze.EntityChangedEventArgs) => {
    if (data.entityAction == breeze.EntityAction.PropertyChange) {
                return this.EntityManager.saveChanges(<breeze.Entity[]> new Array(data.entity))
                    .fail((error) => alert("Failed. " + error));}

        });

数据正确到达事件处理程序。进行了 savechanges 调用,但更改的值 (tenantId) 没有更改。

rowclick 的事件处理程序如下:

ViewModel).OnRowClick = (tenantId: KnockoutObservable<System.IGuid>, viewModel: Imp.Scripts._TenantListViewModel) => {
        entityManager.fetchEntityByKey("User", viewModel.Settings().CurrentUser().UserId(), false)
        .then(entityKeyResult => {
            (<Imp.Classes.UserBreeze>entityKeyResult.entity).CurrentTenantId(tenantId());
            //entityManager.saveChanges(<breeze.Entity[]> new Array(entityKeyResult.entity));
         })
        .fail((error)=> alert("Error setting current tenant. " + error));});

当我禁用 entityChanged 订阅并启用注释行 entityManager.saveChanges.... 时,实体已正确保存。如果我取消注释该行,但保留订阅,它将不起作用。

如何在实体更改后自动保存更改的实体?

编辑: 解决方法是在更改当前用户的 CurrentTenantId 值之前暂时禁用 entityChanged 事件处理程序,手动保存实体并重新订阅 entityChanged 事件。 但是这个解决方案有味道。

【问题讨论】:

    标签: entity-framework knockout.js typescript breeze kogrid


    【解决方案1】:

    一些建议:

    1. 如果频繁触发 propertychanged 事件,请考虑限制保存。为此,Knockout 有一个 rate limiting extender
    2. 您可能还想考虑使用breeze save queuing plugin,这样您就不必担心重叠保存调用。
    3. 要解决保存问题,请尝试在调用 saveChanges 之前立即添加以下代码:

    if (data.entityAction === breeze.EntityAction.PropertyChange) { var pcArgs = <breeze.PropertyChangedEventArgs>data.args; console.log('Property Changed. PropertyName: ' + pcArgs.propertyName + '; Old Value: ' + (pcArgs.oldValue ? pcArgs.oldValue.toString() : 'null') + '; New Value: ' + (pcArgs.newValue ? pcArgs.newValue.toString() : 'null') + ';'); }

    【讨论】:

    • 我已更改您的代码以显示实体类型:属性已更改。属性名:CurrentTenantEntity 类型:UserPoco:#Imp.Persistent;旧值:[object Object];新值:[object Object];属性已更改。属性名:CurrentTenantIdEntity 类型:UserPoco:#Imp.Persistent;旧值:534b1611-9f36-47b5-9e20-d959aa0d97eb;新值:db626552-b8c9-4682-a8ea-5945a54152f0; SaveQueuing 已经打开,我将 rateLimit 设置为 500 毫秒: public CurrentUser: KnockoutObservable = ko.observable().extend({rateLimit: 500});不幸的是问题仍然存在
    • 这意味着保存是在分配 CurrentTenantId 之前发生的,对吧?如果你像这样包装 saveChanges 行怎么办: setTimeout(...save changes code..., 0);
    • 我不认为这意味着保存是在分配 CurrenTenantId 之前发生的。调用该代码是因为 CurrentTenantId 正在 OnRowClick 事件处理程序中分配。然而,SetTimeOut 确实成功了!!谢谢!我无法解释为什么设置为零的超时可以解决我的问题。
    • 我认为发生的是与“CurrentTenantEntity”属性相关的propertychanged 事件触发,触发保存,然后分配“CurrentTenantId”属性,触发第二个propertychanged 事件。 settimeout 技巧允许在调用保存之前分配两个属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2019-10-30
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多