Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It is expected that nothing happens.</p> <p>What you want to change or add is a <em>relationship</em> between the entities <code>Service</code> and <code>ServiceItem</code>. But you cannot manipulate relationships by setting the state of an entity to <code>Modified</code>. This only updates scalar and complex properties but no navigation properties (= relationships). (For example setting the state of a <code>Service</code> entity to <code>Modified</code> will mark <code>Service.Title</code> and <code>Service.Description</code>, etc. as modified and ensure that those properties are saved to the database. But it doesn't care about the content of <code>Service.ServiceItems</code>.)</p> <p>The only exception where you can change a <em>relationship</em> by setting the state to <code>Modified</code> are <em>Foreign Key Associations</em>. These are associations that have foreign key properties exposed in your model entity and they can only occur for one-to-many or one-to-one associations. Many-to-many relationships are always <em>Independent Associations</em> which means they can never have a foreign key property in an entity. (Because the FKs are in the join table, but the join table is not an entity and "hidden" from your model classes.)</p> <p>There is a way to directly manipulate relationships for a many-to-many association but it requires to go down to the <code>ObjectContext</code> and its <code>RelationshipManager</code> which is - in my opinion - pretty advanced and tricky.</p> <p>The usual and straight-forward way to add and remove relationship entries to/from a many-to-many association is by just adding items to and removing items from the collections <em>while the entities are attached</em> to the context. EF's change tracking mechanism will recognize the changes you have done and generate the appropriate INSERT, UPDATE and DELETE statements when you call <code>SaveChanges</code>.</p> <p>The exact procedure depends on if you also want to save <code>Service</code> and/or <code>ServiceItem</code> as new entities or if you only want to add relationships between existing entities. Here are a few examples:</p> <ul> <li><p><code>service</code> should be INSERTed, all <code>serviceItem</code>s should be INSERTed and the relationships between the entities should be INSERTed into the join table as well:</p> <pre><code>using (var context = new MyContext()) { var service = new Service(); var serviceItem1 = new ServiceItem(); var serviceItem2 = new ServiceItem(); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.Services.Add(service); context.SaveChanges(); } </code></pre> <p>Adding the "root" <code>service</code> of the object graph is enough because EF will recognize that all other entities in the graph are not attached to the context and assume that they have to be INSERTed into the database.</p></li> <li><p><code>service</code> already exists and should NOT be INSERTed, all <code>serviceItem</code>s should be INSERTed and the relationships between the entities should be INSERTed into the join table as well:</p> <pre><code>using (var context = new MyContext()) { var service = new Service { ServiceID = 15 }; context.Services.Attach(service); var serviceItem1 = new ServiceItem(); var serviceItem2 = new ServiceItem(); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.SaveChanges(); } </code></pre> <p>EF recognizes here (when <code>SaveChanges</code> is called) that <code>service</code> is attached but the other entities are not. No INSERT for <code>service</code> happens but the <code>serviceItem1/2</code> will be INSERTed together with the relationship entries.</p></li> <li><p><code>service</code> already exists and should NOT be INSERTed, all <code>serviceItem</code>s already exist and should NOT be INSERTed, but the relationships between the entities should be INSERTed into the join table:</p> <pre><code>using (var context = new MyContext()) { var service = new Service { ServiceID = 15 }; context.Services.Attach(service); var serviceItem1 = new ServiceItem { ServiceItemID = 23 }; context.ServiceItems.Attach(serviceItem1); var serviceItem2 = new ServiceItem { ServiceItemID = 37 }; context.ServiceItems.Attach(serviceItem2); service.ServiceItems.Add(serviceItem1); service.ServiceItems.Add(serviceItem2); context.SaveChanges(); } </code></pre></li> <li><p>For completeness: How to <em>remove</em> relationships between existing entities?</p> <pre><code>using (var context = new MyContext()) { var service = context.Services .Include(s =&gt; s.ServiceItems) // load the existing Items .Single(s =&gt; s.ServiceID == 15); var serviceItem1 = service.ServiceItems .Single(s =&gt; s.ServiceItemID == 23); // query in memory, no DB query var serviceItem2 = service.ServiceItems .Single(s =&gt; s.ServiceItemID == 37); // query in memory, no DB query service.ServiceItems.Remove(serviceItem1); service.ServiceItems.Remove(serviceItem2); context.SaveChanges(); } </code></pre> <p>The two relationship rows in the join table that link service 15 with serviceItem 23 and 37 will be deleted.</p></li> </ul> <p>Alternativly instead of calling <code>Attach</code> you can load the existing entities from the database. It will work as well:</p> <pre><code>var service = context.Services.Single(s =&gt; s.ServiceID == 15); </code></pre> <p>And the same for existing <code>ServiceItem</code>s.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload