BreezeJS:为什么在Before/AfterSaveEntitysDelegate中进行的删除没有传播回客户端?

BreezeJS:为什么在Before/AfterSaveEntitysDelegate中进行的删除没有传播回客户端?,breeze,Breeze,我正在使用BreezeJS/Entity框架编写一个简单的活动规划web应用程序-用户创建一个锦标赛实体,并要求服务器生成一个或多个建议计划,其中一个用于本文目的 每当用户单击generate plan时,应将包含生成计划所需的大量详细信息的比赛提交给服务器,服务器应删除任何现有计划,生成新计划,并更新客户端模型 我想,这是一次名副其实的扑救 问题是最后一步:更新客户端模型。服务器添加的计划实体在客户端中按预期显示,但忽略删除。也就是说,客户最终会得到新的和旧的计划 这是我的名字save: [注

我正在使用BreezeJS/Entity框架编写一个简单的活动规划web应用程序-用户创建一个锦标赛实体,并要求服务器生成一个或多个建议计划,其中一个用于本文目的

每当用户单击generate plan时,应将包含生成计划所需的大量详细信息的比赛提交给服务器,服务器应删除任何现有计划,生成新计划,并更新客户端模型

我想,这是一次名副其实的扑救

问题是最后一步:更新客户端模型。服务器添加的计划实体在客户端中按预期显示,但忽略删除。也就是说,客户最终会得到新的和旧的计划

这是我的名字save:

[注:本问题中的描述和代码省略了许多不相关的细节,如20个属性和实体类型,以保持问题的规模]

我猜这是因为_contextProvider.Context已经在缓存中有了旧的计划,所以在它背后删除它(即使用另一个上下文)并没有什么区别

如果然后尝试使用_contextProvider.Context删除它,我会从框架中得到一个奇怪的重复条目错误

我束手无策

编辑2:

以下是IEs开发人员工具记录的保存请求和响应中的数据

首先请求:

{
    "entities": [
        {
            "Id": 1,
            "EventName": "Test Tournament",
            "EventTime": "2015-03-21T20:00:00.000Z",
            "entityAspect": {
                "entityTypeName": "Tournament:#Pontifex.Model",
                "defaultResourceName": "Tournaments",
                "entityState": "Unchanged",
                "originalValuesMap": { },
                "autoGeneratedKey": {
                    "propertyName": "Id",
                    "autoGeneratedKeyType": "Identity"
                }
            }
        }
    ],
    "saveOptions": { }
}
然后,服务器删除现有的计划条目Id=10,并添加一个新的Id=11,我直接在数据库中使用SELECT进行了验证。那很好

但答案是:

[
    {
        "$id": "1",
        "$type": "Pontifex.Model.Tournament, Pontifex.Server",
        "Id": 1,
        "EventName": "Test Tournament",
        "EventTime": "2015-03-21T20:00:00.000",
        "Plans": [
            {
                "$id": "17",
                "$type": "Pontifex.Model.Plan, Pontifex.Server",
                "Id": 11,
                "TournamentId": 1,
                "Tournament": { "$ref": "1" }
            }
        ],
        "BoardPlan": null
    }
]
在这个响应中,删除的实体从未出现,因此客户机将其留在其模型中是可以理解的

添加的计划Id 11将显示,并集成到客户机模型中

但是:从斯贝利斯的回答来看,增加的计划似乎是一个幸运的巧合:

在您的特定示例中,新实体被添加到save中,因为它碰巧与BeforeSaveEntity方法的实体相关,但您不应该依赖它


但是sbelin是一个如何正确添加实体的示例,它似乎不完整,例如,它引用了一个局部变量saveMapAdditions,而该变量在其他地方不使用

我仍然无法将删除操作返回到客户端缓存中……但是如果我的服务器端代码也从所有关系中删除了删除的实体,则删除操作将返回,并且该实体将从客户端模型中消失

更新后的代码我添加了语句Tornament.Plans.RemovedeletePlan:


当然,如果在客户端本地缓存中搜索计划实体,我怀疑删除的计划仍然会出现,因此它不是完美的。但它对我有用

我接受我自己的答案。我不确定这是否是一个糟糕的形式-在背后填充你自己-但它确实描述了我问题的解决方案。。。
{
    "entities": [
        {
            "Id": 1,
            "EventName": "Test Tournament",
            "EventTime": "2015-03-21T20:00:00.000Z",
            "entityAspect": {
                "entityTypeName": "Tournament:#Pontifex.Model",
                "defaultResourceName": "Tournaments",
                "entityState": "Unchanged",
                "originalValuesMap": { },
                "autoGeneratedKey": {
                    "propertyName": "Id",
                    "autoGeneratedKeyType": "Identity"
                }
            }
        }
    ],
    "saveOptions": { }
}
[
    {
        "$id": "1",
        "$type": "Pontifex.Model.Tournament, Pontifex.Server",
        "Id": 1,
        "EventName": "Test Tournament",
        "EventTime": "2015-03-21T20:00:00.000",
        "Plans": [
            {
                "$id": "17",
                "$type": "Pontifex.Model.Plan, Pontifex.Server",
                "Id": 11,
                "TournamentId": 1,
                "Tournament": { "$ref": "1" }
            }
        ],
        "BoardPlan": null
    }
]
[HttpPost]
public SaveResult MyNamedSave(JObject saveBundle)
{
    _contextProvider.BeforeSaveEntitiesDelegate = RecalculatePlan;
    return _contextProvider.SaveChanges(saveBundle);
}

private Dictionary<Type, List<EntityInfo>> RecalculatePlan(Dictionary<Type, List<EntityInfo>> arg)
{
    // See http://stackoverflow.com/questions/14517945/using-this-context-inside-beforesaveentity:
    var readonlyContext = new PontifexContext();

    foreach (var eventInfo in arg[typeof(Tournament)])
    {
        var tournament = (Tournament)eventInfo.Entity;

        var deletePlan = readonlyContext.Plans.First(p => p.TournamentId == tournament.Id);
        arg[typeof(Plan)].Add(_contextProvider.CreateEntityInfo(deletePlan, EntityState.Deleted););

        // Workaround: Remove the deleted plan from all relations:
        tournament.Plans.Remove(deletePlan);

        var addPlan = new Plan {TournamentId = tournament.Id, };
        arg[typeof(Plan)].Add(_contextProvider.CreateEntityInfo(addPlan, EntityState.Added););
    }
}