Note that there are some explanatory texts on larger screens.

plurals
  1. POStrongly-Typed ASP.NET MVC with ADO.NET Entity Framework
    primarykey
    data
    text
    <p>I've finally gotten this working after days of struggle.</p> <p>I've got a simple database of People and Departments:</p> <p><a href="http://img39.imageshack.us/img39/1368/edmxdepartmentperson.gif" rel="nofollow noreferrer">ADO.NET Entity Framework Entity Data Model diagram with Department and Person objects http://img39.imageshack.us/img39/1368/edmxdepartmentperson.gif</a></p> <p>I can use strongly-typed ASP.NET MVC views for reference/navigation properties! See the list of departments...</p> <p><a href="http://img11.imageshack.us/img11/7619/dropdownlistdepartment.gif" rel="nofollow noreferrer">ASP.NET MVC with DropDownList http://img11.imageshack.us/img11/7619/dropdownlistdepartment.gif</a></p> <p>Part of my Person/Edit view:</p> <pre><code>&lt;% using (Html.BeginForm()) {%&gt; &lt;%= Html.Hidden("Id", Model.Id) %&gt; &lt;fieldset&gt; &lt;legend&gt;Fields&lt;/legend&gt; &lt;p&gt; &lt;label for="Name"&gt;Name:&lt;/label&gt; &lt;%= Html.TextBox("Name", Model.Name) %&gt; &lt;/p&gt; &lt;p&gt; &lt;label for="DepartmentId"&gt;Department:&lt;/label&gt; &lt;%= Html.DropDownList("DepartmentId", new SelectList((IEnumerable)ViewData["Departments"], "Id", "Name"))%&gt; &lt;/p&gt; &lt;p&gt; &lt;input type="submit" value="Save" /&gt; &lt;/p&gt; &lt;/fieldset&gt; &lt;% } %&gt; </code></pre> <p>Part of my Person controller:</p> <pre><code>// // GET: /Person/Edit/5 public ActionResult Edit(Guid id) { ViewData["Departments"] = ctx.Department; Person model = (from Person p in ctx.Person where p.Id == id select p).FirstOrDefault(); return View(model); } // // POST: /Person/Edit [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Person model) { ctx.AttachUpdated(model); //extension ctx.SaveChanges(); return RedirectToAction("Index"); } </code></pre> <p>To get this working, I extended the Person EntityObject with a new DepartmentId property.</p> <pre><code>using System; using System.Data; using System.Data.Objects.DataClasses; namespace ProjectName.Models { public partial class Person : EntityObject { public Guid DepartmentId { get { try { return (Guid)this.DepartmentReference.EntityKey.EntityKeyValues[0].Value; } catch { return Guid.Empty; } } set { this.DepartmentReference.EntityKey = new EntityKey("JunkEntities.Department", "Id", value); } } } } </code></pre> <p>And I extended the Entity Framework ObjectContext with new AttachUpdated and ApplyReferencePropertyChanges methods:</p> <pre><code>using System; using System.Data; using System.Data.Objects; using System.Data.Objects.DataClasses; public static class EntityFrameworkExtensionMethods { public static void AttachUpdated(this ObjectContext ctx, EntityObject objectDetached) { if (objectDetached.EntityKey == null) { String entitySetName = ctx.DefaultContainerName + "." + objectDetached.GetType().Name; Guid objectId = (Guid)objectDetached.GetType().GetProperty("Id").GetValue(objectDetached, null); objectDetached.EntityKey = new System.Data.EntityKey(entitySetName, "Id", objectId); } if (objectDetached.EntityState == EntityState.Detached) { object currentEntityInDb = null; if (ctx.TryGetObjectByKey(objectDetached.EntityKey, out currentEntityInDb)) { ctx.ApplyPropertyChanges(objectDetached.EntityKey.EntitySetName, objectDetached); ctx.ApplyReferencePropertyChanges((IEntityWithRelationships)objectDetached, (IEntityWithRelationships)currentEntityInDb); //extension } else { throw new ObjectNotFoundException(); } } } public static void ApplyReferencePropertyChanges(this ObjectContext ctx, IEntityWithRelationships newEntity, IEntityWithRelationships oldEntity) { foreach (var relatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds()) { var oldRef = relatedEnd as EntityReference; if (oldRef != null) { var newRef = newEntity.RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference; oldRef.EntityKey = newRef.EntityKey; } } } } </code></pre> <p>I just wanted to document my progress here. Please suggest improvements.</p> <hr> <p>Thanks:</p> <ul> <li><a href="http://blogs.msdn.com/alexj/archive/2009/03/25/tip-7-faking-foreign-key-properties-in-net-3-5-sp1.aspx" rel="nofollow noreferrer">Alex James</a></li> <li><a href="http://blogs.msdn.com/cesardelatorre/archive/2008/09/04/updating-data-using-entity-framework-in-n-tier-and-n-layer-applications-short-lived-ef-contexts.aspx" rel="nofollow noreferrer">Cesar de la Torre</a></li> <li><a href="http://grifftownsend.blogspot.com/2008/08/small-extension-to-entity-framework.html" rel="nofollow noreferrer">Griff Townsend</a></li> <li><a href="https://stackoverflow.com/questions/898260/entitykey-and-applypropertychanges/898367#898367">Steve Willcock</a></li> <li><a href="https://stackoverflow.com/questions/899734/strongly-typed-asp-net-mvc-with-entity-framework/902202#902202">jrista</a></li> <li><a href="https://stackoverflow.com/questions/895564/entity-framework-with-asp-net-mvc/895688#895688">Tomas Lycken</a></li> <li><a href="https://stackoverflow.com/questions/921106/how-to-create-ado-net-entity-framework-objectcontext-extensions/921303#921303">Thomas Levesque</a></li> <li><a href="http://blogs.msdn.com/dsimmons/archive/2008/01/16/ef-extension-method-extravaganza-part-i-objectstateentry.aspx" rel="nofollow noreferrer">Danny Simmons</a></li> <li><a href="http://www.scip.be/index.php?Page=ArticlesNET26&amp;Lang=NL" rel="nofollow noreferrer">Stefan Cruysberghs</a></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    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