title: ASP.NET MVC with EF 4.1 Navigation properties
body: <p>After days studying EF to understand (kinda..) how it works, I finally realized that I might have a big problem.</p>
  
  <p>Imagine that I have two entities: <code>Pais</code> and <code>UF</code>. The relationship between them is <code>Pais (0..1) ... (*) UF</code>. A screenshot: <a href="https://i.imgur.com/rSOFU.jpg" rel="nofollow noreferrer">http://i.imgur.com/rSOFU.jpg</a>.</p>
  
  <p>Said that, consider that I have a controller called <code>UFController</code> and it has actions for <code>Edit</code> and <code>Create</code>, which are just fine. My views are using the <code>EditorFor</code> helper (or similar ones) for inputs, so when I submit the form the controller will receive a <code>UF</code> object filled with all the data (automatically) with a reference to an <em>almost-empty</em> <code>Pais</code>. My view code (part of it):</p>
  
  <pre><code>@* UF attributes *@
  @Html.EditorFor(m =&gt; m.Sigla)
  @Html.EditorFor(m =&gt; m.Descricao)
  @Html.EditorFor(m =&gt; m.CodigoIBGE)
  @Html.EditorFor(m =&gt; m.CodigoGIA)
  @* Pais primary key ("ID") *@
  @Html.EditorFor(m =&gt; m.Pais.Codigo) // Pais id
  </code></pre>
  
  <p>The controller <code>Edit</code> action code:</p>
  
  <pre><code>[HttpPost]
  public ActionResult Edit(UF uf)
  {
      try
      {
          if (ModelState.IsValid)
          {
              db.UFs.Attach(uf);
              db.ObjectStateManager.ChangeObjectState(uf, EntityState.Modified);
              db.SaveChanges();
  
              return this.ClosePage(); // An extension. Just ignore it.
          }
      }
      catch (Exception e)
      {
          this.ModelState.AddModelError("Model", e.Message.ToString());
      }
  
      return View(uf);
  }
  </code></pre>
  
  <p>When I submit the form, this is what the action receives as <code>uf</code>:</p>
  
  <pre><code>{TOTALWeb.UF}
      base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.UF}
      (...)
      CodigoGIA: 0
      CodigoIBGE: 0
      Descricao: "Foobar 2001"
      ID: 936
      Pais: {TOTALWeb.Pais}
      PaisReference: {System.Data.Objects.DataClasses.EntityReference&lt;TOTALWeb.Pais&gt;}
  </code></pre>
  
  <p>And <code>uf.Pais</code>:</p>
  
  <pre><code>{TOTALWeb.Pais}
      base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.Pais}
      Codigo: 0
      CodigoBACEN: null
      CodigoGIA: null
      CodigoIBGE: null
      Descricao: null
      UF: {System.Data.Objects.DataClasses.EntityCollection&lt;TOTALWeb.UF&gt;}
  </code></pre>
  
  <p>The original information (the one on the database) is <code>uf.Pais.Codigo == 716</code>. So, right now I'm receiving the updated information. The problem on that the controller is not upading the FK in the database.</p>
  
  <p>I don't want to set the EntityState from <code>uf.Pais</code> to <code>Modified</code> because the entity itself wasn't changed (I didn't changed the information from that entry), but the <em>relationship</em> was.</p>
  
  <p>In other words, what I'm trying to do is change the value of the FK, pointing the <code>uf.Pais</code> to another instance of <code>Pais</code>. Afaik, it's impossible to change the relationship state to <code>Modified</code> (throw an exception), so I'm looking for alternative solutions.</p>
  
  <p>I've read a bunch of topics I've found on Google about this kind of problem, but I still didn't find a simple and elegant solution. The last ones I read here on stackoverflow:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/5466384/how-to-work-with-navigation-properties-foreign-keys-in-asp-net-mvc-3-and-ef-4">How to work with navigation properties (/foreign keys) in ASP.NET MVC 3 and EF 4.1 code first</a></li>
  <li><a href="https://stackoverflow.com/questions/922402/strongly-typed-asp-net-mvc-with-ado-net-entity-framework">Strongly-Typed ASP.NET MVC with ADO.NET Entity Framework</a></li>
  <li><a href="https://stackoverflow.com/questions/1369656/getting-error-3007-when-i-add-my-entity-model">Getting Error 3007 when I add my Entity Model</a></li>
  </ul>
  
  <p>I asked a question a few days ago about a similar problem ( <a href="https://stackoverflow.com/questions/6956026/entity-framework-4-1-default-entitystate-for-a-fk">Entity Framework 4.1 - default EntityState for a FK?</a> ). I didn't understand how EF works that time, so now a bunch of things look clear to me (that's why I'm opening a new question).</p>
  
  <p>For the <code>Create</code> action I've been testing this solution (proposed by Ladislav on my other question), but it generates an additional select (which can be eventually slow for us):</p>
  
  <pre><code>// Here UF.Pais is null
  db.UFs.AddObject(uf);
  // Create dummy Pais
  var pais = new Pais { Id = "Codigo" };
  // Make context aware of Pais
  db.Pais.Attach(pais); // &lt;- Executing a SELECT on the database, which -can- be slow.
  // Now make the relation
  uf.Pais = pais;
  db.SaveChanges();
  </code></pre>
  
  <p>I can replicate this for the <code>Edit</code> (I guess), but I don't want that additional SELECT.</p>
  
  <p>So, in resume: I'm trying to use navigation properties to send data to the controller and save them directly in the database using a fast and easy way (without messing too much with the entity - these ones are simple, but we have huge and very complex ones with a lot of FKs!). My question is: there's a solution that doesn't involve executing another query in the database (a simple one)?</p>
  
  <p>Thanks,</p>
  
  <p>Ricardo</p>
  
  <p>PS: sorry for any english mistakes and any confusions.</p>
  
  <p><strong>Update 1</strong>: using BennyM's solution (kind of..)</p>
  
  <p>I tested the following code, but it doesn't work. It throws an exception: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." Probably because Pais is already in the context, I guess?</p>
  
  <p>I'm using a Entities (created by EF) class as context. Also, I don't know what is the method <code>Entry</code>, and I don't know where is it. Just for "fun", I tested this:</p>
  
  <pre><code>// Attach the Pais referenced on editedUF, since editedUF has the new Pais ID, not the old one.
  Pais existingPais = new Pais { Codigo = editedUF.Pais.Codigo };
  db.Paises.Attach(existingPais);
  
  // Attach the edited UF.
  db.UFs.Attach(editedUF);
  
  // Set the correct Pais reference (ignoring the current almost-null one).
  editedUF.Pais = existingPais;
  
  // Change the object state to modified.
  db.ObjectStateManager.ChangeObjectState(editedUF, EntityState.Modified);
  
  // Save changes.
  db.SaveChanges();
  
  return this.ClosePage();
  </code></pre>
  
  <p>The exception is throwed when I try to attach the editedUF to the current context. I'm working with this idea right now, trying to find other solutions. Also, you're right BennyM, attaching the Pais to the context is not generating an additional SELECT. I don't know what happened that time, it really doesn't do anything with the database.</p>
  
  <p>Still, this is a manual solution: I have to do that for each FK. That's what I'm trying to avoid. You see, some programmers, even if you explain 100 times, won't remember to do that with <em>each</em> FK. Eventually that'll come back to me, so I'm trying to avoid anything that can lead into errors (database or code ones) to make sure everyone can work without any stress. :)</p>