使用ADO.NET实体框架键入ASP.NET MVC

经过几天的斗争,我终于得到了这个工作。

我有一个简单的人员和部门数据库:

包含Department和Person对象的ADO.NET实体框架实体数据模型图http://img39.imageshack.us/img39/1368/edmxdepartmentperson.gif

我可以使用强类型的ASP.NET MVC视图来获取参考/导航属性! 查看部门列表...

带有DropDownList的ASP.NET MVC 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");
}

为了得到这个工作,我扩展了Person EntityObject和一个新的DepartmentId属性。

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);
            }
        }
    }
}

我用新的AttachUpdated和ApplyReferencePropertyChanges方法扩展了实体框架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, "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;
            }
        }
    }

}

我只是想在这里记录我的进展。 请提出改进​​建议。


谢谢:

  • Alex James
  • 塞萨尔德拉托雷
  • 格里夫汤森
  • 史蒂夫Willcock
  • jrista
  • Tomas Lycken
  • 托马斯莱维斯克
  • 丹尼西蒙斯
  • Stefan Cruysberghs

  • 我已经开始与ASP.NET MVC合作,这就是为什么我遇到这个线程,所以我不确定你是否还在检查改进。

    我不喜欢将新属性添加到实体框架的部分类的想法,因为它不允许发生太多变化。 尝试标记您的Deparment DropDown“Department.Id”

    <p>
        <label for="Department.Id">Department:</label>
    <%= Html.DropDownList("Department.Id", new SelectList((IEnumerable)ViewData["Departments"], "Id", "Name"))%>
    </p>
    

    MVC框架的ModelBinding将拾取该值并将其应用于“Department”导航属性的“Id”属性。 我发现部门的其他价值为零,但这并不重要。 现在,您可以获取正确的部门实体并将其应用到模型绑定到操作参数中创建的新人员实体的部门导航属性中,如下所示:

    newPerson.Department = ctx.Department.First(d => d.DepartmentId == newPerson.Department.Id);
    

    通过这种方式,您不需要根据实际情况更新实体。


    改进您的编辑控制,以便它处理抛出的异常并重新显示用户迄今为止输入的输入。 我相信你即将;)

    更新你的视图来验证器:

    <label for="Name">Name:</label>
    <%= Html.TextBox("Name", Model.Name) %>
    <%= Html.ValidationMessage("Name", "*") %>
    

    然后在编辑中使用它们:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Person Model)
    {
        try
        {
           ctx.AttachUpdated(Model);  //extension
           ctx.SaveChanges();
           return RedirectToAction("Index");
        }
        catch
        {
            foreach (var err in Model.Errors)
              ModelState.AddModelError(err.PropertyName, err.ErrorMessage)
    
            return View(Model);
        }
    }
    
    链接地址: http://www.djcxy.com/p/33541.html

    上一篇: Typed ASP.NET MVC with ADO.NET Entity Framework

    下一篇: Instance of T (generic type) in Java