经过几天的斗争,我终于得到了这个工作.
我有一个简单的人员和部门数据库:
我可以使用强类型的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);
这样做,您不需要更新您的实体,因为它应该具有的属性.