通过外键关系访问第二个表值

时间:2015-01-01 17:32:27

标签: asp.net asp.net-mvc entity-framework

我正在创建一个应用程序,以便使用ASP,MVC和实体框架。我一直在关注this教程,更改数据模型以满足我的需求。

我在表格中显示了所有用户数据。在我的模型中,我有一个单独的表,供用户参与的教员使用。在包含用户详细信息的页面上,它当前正在显示教师表中的主键。我想在其中显示教师姓名。我怎样才能做到这一点?

使用下面显示的代码我希望能够使用以下代码行来显示教师名称,但是由于变量faculty为null,这会显示一个空字符串的单元格。

@Html.DisplayFor(modelItem => item.faculty.name)

如果我使用PHP,我会做这样的事情;

SELECT faculty_name
FROM   faculties
WHERE  user.school = faculties.id;

用户模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;

namespace Purely_Servers.Models
{
    [Table("userTable")]
    public class user
    {
        [Key]
        public int id { get; set; }
        public string first_name { get; set; }
        public string last_name { get; set; }
        public string email { get; set; }
        public int house_number { get; set; }
        public string street { get; set; }
        public string city { get; set; }
        public string postcode { get; set; }
        public int authorised { get; set; }
        public int school { get; set; }
        public int archived { get; set; }

        public virtual faculty faculty { get; set; }
    }
}

教师模式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;

namespace Purely_Servers.Models
{
    [Table("facultyTable")]
    public class faculty
    {
        [Key]
        public int id { get; set; }
        public string name { get; set; }
        public string location { get; set; }

    }
}

显示用户学校

这当前显示的是与教师表中记录的主键对应的数值。

@model IEnumerable<Purely_Servers.Models.user>

@foreach (var item in Model){
    <tr>
        //other code
        <td>
            @Html.DisplayFor(modelItem => item.school)
        </td>
    </tr>
}

用户控制器

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Purely_Servers.DAL;
using Purely_Servers.Models;

namespace Purely_Servers.Controllers
{
    public class usersController : Controller
    {
        private serverContext db = new serverContext();

        // GET: users
        public ActionResult Index()
        {
            return View(db.Users.ToList());
        }

        // GET: users/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            user user = db.Users.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            return View(user);
        }

        // GET: users/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: users/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "id,first_name,last_name,email,house_number,street,city,postcode,authorised,school,archived")] user user)
        {
            if (ModelState.IsValid)
            {
                db.Users.Add(user);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(user);
        }

        // GET: users/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            user user = db.Users.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            return View(user);
        }

        // POST: users/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "id,first_name,last_name,email,house_number,street,city,postcode,authorised,school,archived")] user user)
        {
            if (ModelState.IsValid)
            {
                db.Entry(user).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

        // GET: users/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            user user = db.Users.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            return View(user);
        }

        // POST: users/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            user user = db.Users.Find(id);
            db.Users.Remove(user);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:1)

Html.DisplayFor使用lambda表达式。您声明modelItem,但在表达式中使用item。您的代码应为:

@Html.DisplayFor(modelItem => modelItem.faculty.name)

根据您的修改:

更简单地说,您可以使用@item.faculty.name

答案 1 :(得分:1)

查看您详细发布的代码,好像您没有正确维护userfaculty之间的关系。

user中,您有一个属性int school {get;set;},您建议该属性代表用户所属设施的外键。这可能确实如此,但您实际上并未通知实体框架。实际上,school属性是不必要的。

在“创建”操作中,您接受int school作为参数(可能是从下拉列表中派生的int)。然后,您继续将其保存为数据库中的值,并且实体框架很乐意这样做,而实际上这代表了一种关系。

您在创建操作中可能打算做的更像是:

if (ModelState.IsValid)
{
    db.Users.Add(user);
    // Find Faculty in the database and add the user to the faculty's collection.
    var faculty = db.Faculty.Find(school);
    faculty.users.add(user);

    db.SaveChanges();
    return RedirectToAction("Index");
}

现在,school参数是不必要的,因为它是faculty.id

的副本

在您的Details操作中,您现在可以使用Include()faculty一起发送user,如下所示:

user user = db.Users.Include(u => u.faculty).SingleOrDefault(u => u.id == id);

(请注意,添加Include需要使用SingleOrDefault而不是Find。如果启用了延迟加载,则Include并非完全必要,但< em> 效率更高。)

有了这个,item.faculty不再是null,您可以输出item.faculty.iditem.faculty.name等。

以下是Loading related entities上MSDN文章的链接。