title: Entity Framework automatic foreign key population
body: <p>Is there any way to force Entity Framework to populate the foreign keys immediately when an entity is added to the context, rather than delaying it until something else happens with the context?  This default behavior is not very helpful when using data binding to display referenced entities.</p>
  
  <p>Just referencing any <code>DbSet</code> from the context is enough to force EF to populate the <code>Parent</code> and <code>Parent_Name</code> of the added <code>Children</code>.  But nothing short of <code>SaveChanges</code> seems to force EF to populate the <code>Reference</code> or <code>Reference_Name</code>.</p>
  
  <p>I'd really like to mark <code>Reference_Name</code> with the <code>[Required]</code> ttribute so it will be <code>Not Null</code> in the database, but if I do that, I get validation errors when I try to call <code>SaveChanges</code> unless I've explicitly set the <code>Reference_Name</code>, even though <code>SaveChanges</code> itself will correctly populate <code>Reference_Name</code> if Reference is set.</p>
  
  <p>I'd really like to be able to set either <code>Reference</code> or <code>Reference_Name</code> and be able to immediately use the other.  Likewise, I'd like to be able to immediately use <code>Parent</code> or <code>Parent_Name</code> after adding the <code>Child</code> object, without having to use the kludge of accessing some other element from the context first.</p>
  
  <p>Can anyone help me understand why EF delays these things, and how I can force it to populate the foreign key properties or the foreign key columns, preferably immediately but at least without having to call <code>SaveChanges</code>?  I'd really prefer not to have to fully populate all the properties explicitly when EF is going to correctly populate them anyway.</p>
  
  <pre><code>public class OracleContext : DbContext
  {
      public virtual DbSet&lt;Parent&gt; Parents { get; set; }
      public virtual DbSet&lt;Child&gt; Children { get; set; }
      public virtual DbSet&lt;Reference&gt; References { get; set; }
      public virtual DbSet&lt;SomethingElse&gt; SomethingElses { get; set; }
  }
  
  public class Parent
  {
      [Key, MaxLength(30)]
      public string Name { get; set; }
  
      [InverseProperty("Parent")]
      public virtual List&lt;Child&gt; Children { get; set; } = new List&lt;Child&gt;();
  }
  
  public class Child
  {
      [Key, Column(Order = 1), MaxLength(30)]
      public string Parent_Name { get; set; }
  
      [Key, Column(Order = 2), MaxLength(30)]
      public string Name { get; set; }
  
      public string Reference_Name { get; set; }
  
      [ForeignKey("Parent_Name")]
      public virtual Parent Parent { get; set; }
  
      [ForeignKey("Reference_Name")]
      public virtual Reference Reference { get; set; }
  
      public Child Clone()
      {
          return new Child
          {
              Parent_Name = this.Parent_Name,
              Name = this.Name,
              Reference_Name = this.Reference_Name,
              Parent = this.Parent,
              Reference = this.Reference
          };
      }
  }
  
  public class Reference
  {
      [Key, MaxLength(30)]
      public string Name { get; set; }
  }
  
  public class SomethingElse
  {
      [Key, MaxLength(30)]
      public string Name { get; set; }
  }
  
  private void button1_Click(object sender, EventArgs e)
  {
      OracleContext context = new OracleContext();
  
      Reference reference = context.References.Add(new Reference { Name = "Reference" });
  
      Parent alpha = context.Parents.Add(new Parent { Name = "Alpha" });
  
      Child alphaOne = new Child { Name = "AlphaOne" };
      Child alphatwo = new Child { Name = "AlphaTwo", Reference_Name = "Reference" };
      alpha.Children.AddRange(new List&lt;Child&gt; { alphaOne, alphatwo });
      alphaOne.Reference = reference;
  
      var list = (
              from child in alpha.Children
              select new
              {
                  Time = "Before referencing SomethingElses.Local",
                  Child = child.Clone()
              }
          ).ToList();
  
      var x = context.SomethingElses.Local;
  
      list.AddRange(
              from child in alpha.Children
              select new
              {
                  Time = "After referencing SomethingElses.Local",
                  Child = child.Clone()
              }
          );
  
      list.AddRange(
              from parent in context.Parents.Local
              from child in parent.Children
              select new
              {
                  Time = "Before SaveChanges",
                  Child = child.Clone()
              }
          );
  
      context.SaveChanges();
  
      list.AddRange(
              from parent in context.Parents.Local
              from child in parent.Children
              select new
              {
                  Time = "After SaveChanges",
                  Child = child.Clone()
              }
          );
  
      foreach (var item in list)
      {
          Console.WriteLine("{0}:\r\n\tName = '{1}'\r\n\tParent = '{2}' ({3})\r\n\tReference = '{4}' ({5})",
              item.Time, item.Child.Name, item.Child.Parent_Name, item.Child.Parent, item.Child.Reference_Name, item.Child.Reference);
      }
  }
  
  Before referencing SomethingElses.Local:
      Name = 'AlphaOne'
      Parent = '' ()
      Reference = '' (WindowsFormsApplication2.Reference)
  Before referencing SomethingElses.Local:
      Name = 'AlphaTwo'
      Parent = '' ()
      Reference = 'Reference' ()
  After referencing SomethingElses.Local:
      Name = 'AlphaOne'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = '' (WindowsFormsApplication2.Reference)
  After referencing SomethingElses.Local:
      Name = 'AlphaTwo'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = 'Reference' ()
  Before SaveChanges:
      Name = 'AlphaOne'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = '' (WindowsFormsApplication2.Reference)
  Before SaveChanges:
      Name = 'AlphaTwo'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = 'Reference' ()
  After SaveChanges:
      Name = 'AlphaOne'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = 'Reference' (WindowsFormsApplication2.Reference)
  After SaveChanges:
      Name = 'AlphaTwo'
      Parent = 'Alpha' (WindowsFormsApplication2.Parent)
      Reference = 'Reference' (WindowsFormsApplication2.Reference)
  </code></pre>