在MVC 5和EF 6.1中建立多对多关系的CRUD屏幕

时间:2015-04-10 14:41:35

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

我不知道如何构建多对多关系,并为用户提供输入数据的正确表单。我有一个Class对象,我有一个教师对象,教师可以有很多班级,班级可以有很多老师,我不能使用复选框,因为我们拥有的教师人数超过100人以及班级。我的模型如下

 public abstract class Person
{
    public int PersonId { get; set; }
    [Required]
    [StringLength(50, ErrorMessage = "First name can not be longer than 50 characters.")]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }
    [Required]
    [StringLength(50, ErrorMessage = "Last name can not be longer than 50 characters.")]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    [Display(Name = "Middle Initial")]
    public string MidInit { get; set; }
    [Display(Name = "Contact Number")]
    public string PhoneNo { get; set; }
    [EmailAddress]
    [Display(Name = "Work Email")]
    public string Email { get; set; }
    [DataType(DataType.MultilineText)]
    [Display(Name = "Notes")]
    public string Notes { get; set; }
    public int? ConsId { get; set; }
    public string FullName
    {
        get
        {
            string firstName = string.IsNullOrWhiteSpace(this.FirstName) ? "" : this.FirstName;
            string midInit = string.IsNullOrWhiteSpace(this.MidInit) ? "" : this.MidInit;
            string lastName = string.IsNullOrWhiteSpace(this.LastName) ? "" : this.LastName;
            return string.Format("{0} {1} {2} {3} {4}", firstName, " ", midInit, " ", LastName);
        }
    }    
}    
public class Teacher : Person
{
    public Teacher()
    {
        Classes = new HashSet<AClass>();
    }

    [Display(Name = "Classes Taught")]
    public virtual ICollection<AClass> Classes { get; set; }

    public override string ToString()
    {
        return this.PersonId.ToString();
    }
}
public class AClass
{
    public AClass()
    {
        Instructors = new HashSet<Teacher>();
        ClassEndDate = DateTime.Today;
    }
    public int AClassId { get; set; }
    [Display(Name = "Class Number")]
    public string ClassNo { get; set; }
    [Display(Name = "Class Name")]
    public string ClassName { get; set; }
    [Display(Name = "Section Number")]
    public string SectionNumber { get; set; }
    [DataType(DataType.Date)]
    [Display(Name = "Class Start Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
    [Required]
    public DateTime ClassStartDate { get; set; }
    [DataType(DataType.Time)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:hh:mm tt}")]
    [Display(Name = "Class Start Time")]
    public DateTime? ClassStartTime { get; set; }
    [Display(Name = "Class End Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
    [Required]
    public DateTime ClassEndDate { get; set; }
    public virtual ICollection<Teacher> Instructors { get; set; }
    public IEnumerable<int> ClassInstructorId { get; set; }
    public ICollection<Teacher> AllInstructors { get; set; } 
    public string ClassDisplay
    {
        get
        {
            return ClassNo + " - " + ClassName + " Start Date: " + ClassStartDate.ToShortDateString();
        }
    }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public DbSet<AClass> Classes { get; set; }
    public DbSet<Person> Persons { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<AClass>().HasMany<Teacher>(i => i.Instructors).WithMany(c => c.Classes).Map(m =>
        {
            m.MapLeftKey("AClassId");
            m.MapRightKey("PersonId");
            m.ToTable("ClassInstructor");
        });
        modelBuilder.Entity<IdentityUserLogin>().ToTable("AspNetUsers").HasKey<string>(l => l.UserId);
        modelBuilder.Entity<IdentityRole>().ToTable("AspNetRoles").HasKey<string>(r => r.Id);
        modelBuilder.Entity<IdentityUserRole>().ToTable("AspNetUserRoles").HasKey(r => new { r.RoleId, r.UserId });
        base.OnModelCreating(modelBuilder);
    }
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

我的crud创建表单我将其修改为包含多选列表如下

@using (Html.BeginForm()) 

{     @ Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>AClass</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.ClassNo, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ClassNo, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ClassNo, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ClassName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ClassName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ClassName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SectionNumber, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.SectionNumber, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.SectionNumber, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.Label("Teacher", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-5">
            @Html.ListBoxFor(model => model.ClassInstructorId, new MultiSelectList(Model.AllInstructors, "PersonID", "FullName"), new { Multiple = "multiple" })

        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ClassStartDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ClassStartDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ClassStartDate, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ClassStartTime, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ClassStartTime, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ClassStartTime, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ClassEndDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ClassEndDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ClassEndDate, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

我的类控制器如下创建操作

       // GET: Classes/Create
    public ActionResult Create()
    {
        AClass model = new AClass();
        model.AllInstructors = db.Persons.OfType<Teacher>().ToList();
        model.ClassInstructorId = Enumerable.Empty<int>();
        foreach (Teacher inst in model.Instructors)
        {
            model.ClassInstructorId = model.ClassInstructorId.Concat(new[] { inst.PersonId });
        }
        model.ClassStartDate = DateTime.Today;
        return View(model);
    }

    // POST: Classes/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 = "AClassId,ClassNo,ClassName,SectionNumber,ClassStartDate,ClassStartTime,ClassEndDate")] AClass aClass)
    public ActionResult Create(AClass aClass, )

    {
        if (ModelState.IsValid)
        {
            db.Classes.Add(aClass);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(aClass);
    }

表已成功创建,但我的问题是如何在创建类时将教师分配给类,以及如何在编辑的情况下将它们带回来。任何见解将不胜感激。我虽然EF处理相关数据。

1 个答案:

答案 0 :(得分:0)

这就是我所做的,它像魅力一样工作感谢您的帮助,我希望这段代码可以帮助我所在地的其他人。

我将classId从int

更改为Guid

然后在我的控制器Post方法

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(AClass aClass, )

{
    if (ModelState.IsValid)
    {
        aClass.AClassId = Guid.NewGuid();
        aClass.Instructors = db.Persons.OfType<Teacher>().Where(m => aClass.ClassInstructorId.Contains(m.PersonId)).ToList();
        db.Classes.Add(aClass);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(aClass);
}

和entityframework负责其余部分。