Breeze Foreign key navigation property not sent to save bundle when saving changes caused by

I'm having trouble trying to save a new child through the breeze, my model comes down to this

Parent Foo has zero or more children of type bar, i.e. Parent has a property of type ICollection, called bars, and a Bar object has a property of type Foo - its parent

I can extract, update and insert new instances of the β€œparent” Foo objects via Breeze - this uses the web api controller, but I get a violation of the restrictions when creating a new Bar instance, setting its parent Foo (already in the cache) and causing save changes

I have code similar to this

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

I also tried adding a child to my parents collection, for example existingFoo.bars.push (newBar);

and explicitly calling entityManager.addEntity (newBar);

before calling save changes, but the error is the same

Checking that the JObject saveBundle is passed to the controller, I see the new object of the child bar, but I do not see the reference to the parent object

Is it a simple-to-many relationship that I think is supported? - I see a metadata relationship that looks right

The exception message is as follows

Entities in 'FooBarContext.Bars' participate in the relation 'Foo_Bars'. 0 related "Foo_Bar_Source".

What am I doing wrong?

Update 1: Metadata generated by the controller:

"{\" 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 \": \ " stan \ ", \" nullable \ ": \" true \ "}], \" navigationProperty \ ": {\" name \ ": \" Children \ ", \" relationships \ ": \" Self.Bar_Parent \ " , \ "fromRole \": \ "Bar_Parent_Target \", \ "toRole \": \ "Bar_Parent_Source \"}}, {\ "name \": \ "Bar \", \ "key \": {\ "propertyRef \ ": {\" name \ ": \" Id \ "}}, \" property \ ": [{\" name \ ": \" Id \ ", \" type \ ": \" EDM. Int 32 \ ", \" nullable \ ": \" fake \ ", \" 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 \ "}}], \" union \ ": {\" 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 \ ", \" associations \ ": \" Self.Bar_Parent \ ", \" end \ ": [{\ "role \": \ "Bar_Parent_Source \", \ "EntitySet \": \ "Bars \"}, {\ "role \": \ "Bar_Parent_Target \", \ "EntitySet \": \ "Foos \"}] }}}} "

Code example:

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

generated request payload:

{"entity": [{"Id": - 1, "Description": "bar desc", "entityAspect": {"entityTypeName": "Bar: # BreezePlayground.Models", "entityState": "Added", " originalValuesMap ": {}," autoGeneratedKey ": {" PropertyName ":" Identifier "," autoGeneratedKeyType ":" identity "}}}]," SaveOptions ": {" allowConcurrentSaves ": false}}

A child object was entered, but the foreign key is not set

I assume this is due to the display of ef and the generated metadata?

Update 2: Do you need a foreign key property?

I compared my code with the new Breeze SPA code template, which obviously works, and the key difference I found in the generated metadata was that the ToDo application model provides the foreign key of the parent object.

I added this to my simple Foo Bar model and was able to get the child to be saved for work - I understand that ef does not have to expose the foreign key in the model, but does it seem like a requirement for Breeze to generate the correct metadata? β€œDid I miss this in the documents somewhere?”

+4
source share
1 answer

Good booty! We need to better document this, and as a result of this message are in the process of updating documents on this topic.

As you discovered, the breeze suggests that you use "foreign key associations" instead of "independent associations" (in EF).

The reason for this requirement, which can be circumvented, but with a significant loss of functionality, is that the presence of foreign keys on the client is something that makes it easy to configure relationships between objects that can be requested separately.

See the following MSDN article for more information: foreign-keys-in-the-entity-framework

+4
source

All Articles