title: EF 5.0 new object: assign foreign key property does not set the foreign key id, or add to the collection
body: <p>EF 5.0, using code-first on existing database workflow.
  Database has your basic SalesOrder and SalesOrderLine tables with <em>required</em> foreign key on the SalesOrderLine as follows;</p>
  
  <pre><code>public class SalesOrder
  {
      public SalesOrder()
      {
          this.SalesOrderLines = new List&lt;SalesOrderLine&gt;();
      }
  
      public int SalesOrderID { get; set; }
      public int CustomerID { get; set; }
      public virtual Customer Customer { get; set; }
  
      public virtual ICollection&lt;SalesOrderLine&gt; SalesOrderLines { get; set; }
  }
  
  public class SalesOrderLine
  {
      public SalesOrderLine()
      {
      }
      public int SalesOrderLineID { get; set; }
      public int SalesOrderID { get; set; }
  
      public virtual SalesOrder SalesOrder { get; set; }
  }
  public SalesOrderLineMap()
  {
      // Primary Key
      this.HasKey(t =&gt; t.SalesOrderLineID);
      // Table &amp; Column Mappings
      this.ToTable("SalesOrderLine");
      this.Property(t =&gt; t.SalesOrderLineID).HasColumnName("SalesOrderLineID");
      this.Property(t =&gt; t.SalesOrderID).HasColumnName("SalesOrderID");
  
      // Relationships
      this.HasRequired(t =&gt; t.SalesOrder)
          .WithMany(t =&gt; t.SalesOrderLines)
          .HasForeignKey(d =&gt; d.SalesOrderID);
  }
  </code></pre>
  
  <p>Now according to this page:
  <a href="http://msdn.microsoft.com/en-us/data/jj713564" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/data/jj713564</a></p>
  
  <p>...we are told that:</p>
  
  <blockquote>
    <p>The following code removes a relationship by setting the foreign key
    to null. Note, that the foreign key property must be nullable.</p>
    
    <p>course.DepartmentID = null;</p>
    
    <p><em>Note: If the reference is in the added state (in this example, the
    course object), the reference navigation property will not be
    synchronized with the key values of a new object until SaveChanges is
    called. Synchronization does not occur because the object context does
    not contain permanent keys for added objects until they are saved. If
    you must have new objects fully synchronized as soon as you set the
    relationship, use one of the following methods.</em></p>
    
    <p><strong>By assigning a new object to a navigation property. The following code
    creates a relationship</strong> between a course and a department. If the
    objects are attached to the context, the course is also added to the
    department.Courses collection, and the corresponding foreign key
    property on the course object is set to the key property value of the
    department.</p>
    
    <p>course.Department = department;</p>
  </blockquote>
  
  <p>...sounds good to me!</p>
  
  <p>Now my problem: 
  I have the following code, and yet both of the the Asserts fail - why? </p>
  
  <pre><code>    using (MyContext db = new MyContext ())
      {
          SalesOrder so = db.SalesOrders.First();
          SalesOrderLine sol = db.SalesOrderLines.Create();
          sol.SalesOrder = so;
  
          Trace.Assert(sol.SalesOrderID == so.SalesOrderID);
          Trace.Assert(so.SalesOrderLines.Contains(sol));
      }
  </code></pre>
  
  <p>Both objects are attached to the context - are they not? Do I need to do a SaveChanges() before this will work? If so, that seems a little goofy and it's rather annoying that I need to set all of the references on the objects by hand when a new object is added to a foreign-key collection.</p>
  
  <p>-- UPDATE --</p>
  
  <p>I should mark Gert's answer as correct, but I'm not very happy about it, so I'll wait a day or two. ...and here's why:</p>
  
  <p>The following code does not work either:</p>
  
  <pre><code>SalesOrder so = db.SalesOrders.First();
  SalesOrderLine sol = db.SalesOrderLines.Create();
  db.SalesOrderLines.Add(sol);
  
  sol.SalesOrder = so;
  Trace.Assert(so.SalesOrderLines.Contains(sol));
  </code></pre>
  
  <p>The only code that <em>does</em> work is this:</p>
  
  <pre><code>SalesOrder so = db.SalesOrders.First();
  SalesOrderLine sol = db.SalesOrderLines.Create();
  
  sol.SalesOrder = so;
  db.SalesOrderLines.Add(sol);
  
  Trace.Assert(so.SalesOrderLines.Contains(sol));
  </code></pre>
  
  <p>...in other words, you have to set all of your foreign key relationships first, and then call TYPE.Add(newObjectOfTYPE)
  before any of the relationships and foreign-key fields are wired up. This means that from the time the Create is done until the time you do the Add(), the object is basically in a half-baked state. I had (mistakenly) thought that since I used Create(), and since Create() returns a sub-classed dynamic object (as opposed to using "new" which returns a POCO object) that the relationships wire-ups would be handled for me. It's also odd to me, that you can call Add() on an object created with the <em>new</em> operator and it will work, even though the object is not a sub-classed type... </p>
  
  <p>In other words, this will work:</p>
  
  <pre><code>    SalesOrder so = db.SalesOrders.First();
      SalesOrderLine sol = new SalesOrderLine();
  
      sol.SalesOrder = so;
      db.SalesOrderLines.Add(sol);
  
      Trace.Assert(sol.SalesOrderID == so.SalesOrderID);
      Trace.Assert(so.SalesOrderLines.Contains(sol));
  </code></pre>
  
  <p>...I mean, that's cool and all, but it makes me wonder; what's the point of using "Create()" instead of new, if you're always going to have to Add() the object in either case if you want it properly attached?</p>
  
  <p><strong>Most annoying to me is that the following fails;</strong></p>
  
  <pre><code>SalesOrder so = db.SalesOrders.OrderBy(p =&gt; p.SalesOrderID).First();
  SalesOrderLine sol = db.SalesOrderLines.Create();
  
  sol.SalesOrder = so;
  db.SalesOrderLines.Add(sol);
  
   // NOTE: at this point in time, the SalesOrderId field has indeed been set to the SalesOrderId of the SalesOrder, and the Asserts will pass...
  Trace.Assert(sol.SalesOrderID == so.SalesOrderID);
  Trace.Assert(so.SalesOrderLines.Contains(sol));
  
  sol.SalesOrder = db.SalesOrders.OrderBy(p =&gt; p.SalesOrderID).Skip(5).First();
  
   // NOTE: at this point in time, the SalesOrderId field is ***STILL*** set to the SalesOrderId of the original SO, so the relationships are not being maintained! 
  // The Exception will be thrown!
  if (so.SalesOrderID == sol.SalesOrderID)
      throw new Exception("salesorderid not changed");
  </code></pre>
  
  <p>...that seems like total crap to me, and makes me feel like the EntityFramework, even in version 5, is like a minefield on a rice-paper bridge. Why would the above code not be able to sync the SalesOrderId on the second assignment of the SalesOrder property? What essential trick am I missing here?</p>