4

我在尝试通过微风保存新子对象时遇到问题,我的模型归结为

Parent Foo 有零个或多个 bar 类型的子对象,即 Parent 有一个 ICollection 类型的属性,称为 bar,而 Bar 对象有一个 Foo 类型的属性 - 它的 parent

我可以通过 Breeze 获取、更新和插入“父”Foo 对象的新实例——这是使用 Web api 控制器,但是在创建 Bar 的新实例、设置其父 Foo(已经在缓存中)时出现约束冲突,并且调用保存更改

我有类似的代码

var newBar = entityManager.createEntity("Bar");
newBar.Foo = existingFoo;
entityManager.saveChanges();

我也尝试将孩子添加到父母集合中,例如existingFoo.bars.push(newBar);

并显式调用
entityManager.addEntity(newBar);

在调用保存更改之前,但错误是相同的

检查传递给控制器​​的 JObject saveBundle 我可以看到新的子栏对象,但我没有看到对父对象的任何引用

这是我认为支持的简单的一对多关系?- 我可以看到看起来正确的元数据中的关系

异常消息如下所示

“FooBarContext.Bars”中的实体参与“Foo_Bars”关系。找到 0 个相关的“Foo_Bar_Source”。

我究竟做错了什么?

更新 1:控制器生成的元数据:

"{\"schema\":{\"namespace\":\"BreezePlayground.Models\",\"alias\":\"Self\",\"d4p1:UseStrongSpatialTypes\":\"false\",\ "xmlns:d4p1\":\" http://schemas.microsoft.com/ado/2009/02/edm/annotation \",\"xmlns\":\" http://schemas.microsoft.com/ado /2009/11/edm\",\"cSpaceOSpaceMapping\":\"[[\\"BreezePlayground.Models.Foo\\",\\"BreezePlayground.Models.Foo\\"],[\\"BreezePlayground.Models.Bar\\" ,\\"BreezePlayground.Models.Bar\\"]]\",\"entityType\":[{\"name\":\"Foo\",\"key\":{\"propertyRef\": {\"name\":\"Id\"}},\"property\":[{\"name\":\"Id\",\"type\":\"Edm.Int32\",\ "nullable\":\"false\",\"d4p1:StoreGeneratedPattern\":\"Identity\"},{\"name\":\"Name\",\"type\":\"Edm.String \",\"fixedLength\":\"false\",\"maxLength\":\"Max\",\"unicode\":\"true\",\"nullable\":\"true\" }],\"navigationProperty\":{\"name\":\"Children\",\"relationship\":\"Self.Bar_Parent\",\"fromRole\":\"Bar_Parent_Target\",\"toRole\" :\"Bar_Parent_Source\"}},{\"name\":\"Bar\",\"key\":{\"propertyRef\":{\"name\":\"Id\"}}, \"property\":[{\"name\":\"Id\",\"type\":\"Edm.Int32\",\"nullable\":\"false\",\"d4p1: StoreGeneratedPattern\":\"Identity\"},{\"name\":\"Description\",\"type\":\"Edm.String\",\"fixedLength\":\"false\", \"maxLength\":\"Max\",\"unicode\":\"true\",\"nullable\":\"true\"}],\"navigationProperty\":{\"name\":\"Parent\",\"relationship\":\"Self.Bar_Parent\",\"fromRole\":\"Bar_Parent_Source\",\"toRole\":\ "Bar_Parent_Target\"}}],\"association\":{\"name\":\"Bar_Parent\",\"end\":[{\"role\":\"Bar_Parent_Source\",\"type \":\"Edm.Self.Bar\",\"multiplicity\":\"*\"},{\"role\":\"Bar_Parent_Target\",\"type\":\"Edm.Self .Foo\",\"multiplicity\":\"0..1\"}]},\"entityContainer\":{\"name\":\"FooBarContext\",\"entitySet\":[{ \"name\":\"Foos\",\"entityType\":\"Self.Foo\"},{\"name\":\"Bars\",\"entityType\":\"Self.Bar\"}],\"associationSet\":{\"name\":\"Bar_Parent\",\"association\":\"Self.Bar_Parent\",\"end \":[{\"role\":\"Bar_Parent_Source\",\"entitySet\":\"Bars\"},{\"role\":\"Bar_Parent_Target\",\"entitySet\":\ "Foos\"}]}}}}"

示例代码:

 var managerInsert = new breeze.EntityManager("/api/FooBar");
    managerInsert.fetchMetadata().then(function () {
        managerInsert.fetchEntityByKey('Foo', 1, false)
        .then(function (data) {
            var child = managerInsert.createEntity('Bar');
            child.Parent(data.entity);
            child.Description("bar desc");
            managerInsert.saveChanges().then(function () {
                return true;
            })
                .fail(function () {
                    alert('save failed');
                });
        })
        .fail(function (data) {
            alert('fail');
        });
    });

生成的请求有效载荷:

{"entities":[{"Id":-1,"Description":"bar desc","entityAspect":{"entityTypeName":"Bar:#BreezePlayground.Models","entityState":"Added"," originalValuesMap":{},"autoGeneratedKey":{"propertyName":"Id","autoGeneratedKeyType":"Identity"}}}],"saveOptions":{"allowConcurrentSaves":false}}

插入了子对象但未设置外键

我假设这与 ef 映射和生成的元数据有关?

更新 2:需要外键属性?

我将我的代码与新的 Breeze SPA 模板 ToDo 应用程序代码进行了比较,该代码显然有效,我在生成的元数据中发现的主要区别是 ToDo 应用程序模型公开了父对象外键。

我将它添加到我的简单 Foo Bar 模型中,并且能够保存子对象来工作 - 我的理解是 ef 使得在模型中公开外键是可选的,但似乎这是 Breeze 的要求生成正确的元数据?- 我在某处的文档中错过了吗?

4

1 回答 1

4

接得好!我们确实需要更好地记录这一点,并且由于这篇文章正在更新关于这个主题的文档。

正如您所发现的,微风假定您使用的是“外键关联”而不是“独立关联”(用 EF 的说法)。

这个要求可以被绕过,但会导致大量功能损失,其原因是客户端上存在外键允许微风自动修复可能单独查询的实体之间的关系。

有关更多背景信息,请参阅以下 MSDN 文章:foreign-keys-in-the-entity-framework

于 2013-03-05T01:14:29.897 回答