经过几天的斗争,我终于得到了这个工作.
我有一个简单的人员和部门数据库:
我可以使用强类型的ASP.NET MVC视图参考/导航属性!查看部门清单…
ASP.NET MVC with DropDownList http://img11.imageshack.us/img11/7619/dropdownlistdepartment.gif
我的人/编辑视图的一部分:
<% using (Html.BeginForm()) {%> <%= Html.Hidden("Id",Model.Id) %> <fieldset> <legend>Fields</legend> <p> <label for="Name">Name:</label> <%= Html.TextBox("Name",Model.Name) %> </p> <p> <label for="DepartmentId">Department:</label> <%= Html.DropDownList("DepartmentId",new SelectList((IEnumerable)ViewData["Departments"],"Id","Name"))%> </p> <p> <input type="submit" value="Save" /> </p> </fieldset> <% } %>
我的人员控制器的一部分:
// // 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"); }
为了得到这个工作,我用一个新的DepartmentId属性扩展了Person EntityObject.
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",value); } } } }
并且我用新的AttachUpdated和ApplyReferencePropertyChanges方法扩展了Entity Framework ObjectContext:
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,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; } } } }
我只想记录我在这里的进度.请建议改进.
谢谢:
> Alex James
> Cesar de la Torre
> Griff Townsend
> Steve Willcock
> jrista
> Tomas Lycken
> Thomas Levesque
> Danny Simmons
> Stefan Cruysberghs
解决方法
我已经开始使用ASP.NET MVC,这就是为什么我来到这个线程,所以我不知道你是否仍在检查改进.
我不喜欢将这个新属性添加到实体框架上的部分类中,因为它不允许有太多变化.
尝试标记你的Deparment DropDown“Department.Id”这样
<p> <label for="Department.Id">Department:</label> <%= Html.DropDownList("Department.Id","Name"))%> </p>
MVC框架的ModelBinding将获取该值并将其应用于“部门”导航属性的“Id”属性.我发现部门的其他价值是空的,但这并不重要.现在,您有一种方法来检索正确的部门实体并将其应用于在“绑定到您的Action”参数中创建的新Person实体的部门导航属性,如下所示:
newPerson.Department = ctx.Department.First(d => d.DepartmentId == newPerson.Department.Id);
这样做,您不需要更新您的实体,因为它应该具有的属性.