C# 构建\创建mvc5模型(代码优先),该模型具有固定数量的多个元素的一对多(N-arry?)关系

C# 构建\创建mvc5模型(代码优先),该模型具有固定数量的多个元素的一对多(N-arry?)关系,c#,asp.net,model,asp.net-mvc-5,ef-code-first,C#,Asp.net,Model,Asp.net Mvc 5,Ef Code First,这是我的第一个问题,如果我做错了,很抱歉。我在这里找不到答案 我需要使用以下元数据构建数据库: public class Room { [Key] public int RoomID { get; set; } public string Name { get; set; } public virtual ICollection<Student> Students {get;set;} } public class Student { [K

这是我的第一个问题,如果我做错了,很抱歉。我在这里找不到答案

我需要使用以下元数据构建数据库:

public class Room
{
    [Key]
    public int RoomID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Student> Students {get;set;}
}

public class Student 
{
    [Key]
    public int StudentID { get; set; }
    public string Name { get; set; }
}
但我正在寻找更优雅的解决方案

我还知道我可以在房间创建/编辑操作的控制器中控制学生人数

但我只想更改DB模型,除非没有其他解决方案


谢谢,

这似乎可以通过EF的验证功能实现:

您可以尝试在其中一个类上实现,以验证学生人数是否低于最大限制。在过去,我会从关系的方方面面这样做,但你的学生模型似乎没有提到它的房间。 另一个选项是重写DbContext.ValidateEntity。 在任何一种情况下,都会在调用DbContext.SaveChanges或DbContext.GetValidationErrors时进行验证


有关实体框架验证的更多信息,请参见。

感谢@jjj和这里的所有帮助,这就是我解决此问题的方法 基于IValidatableObject实现:

模型:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;

namespace College.Models
{
    public class Student : IValidatableObject
    {
        [Key]
        public int StudentID { get; set; }
        public string Name { get; set; }
        public virtual Room Room { get; set; }

        //validation:
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {

            if (Room.Students.Count() > 20)
                yield return new ValidationResult("Too many students in class", new[] { "RoomId" });
        }


    }

public class Room
{
    public Room()
    {
        Students = new List<Student>();
    }

    [Key]
    public int RoomID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Student> Students {get;set;}

}

}
视图:


有几个选择。您可以重写SaveC改,或者这里的选项之一:您需要考虑EF只能对内存中的数据进行验证。强制执行的唯一方法是每次添加学生时,检索该房间的所有现有学生或发出计数查询。如果您有AddStudent操作,则每次都必须查询DB以检查并查看房间中当前有多少学生。据我所知,没有办法创建一个DB级别的约束来强制执行这一点,一个过于复杂的触发器可能会这样做。我强烈认为这个逻辑是在你的业务层而不是数据模型的一部分。我知道这不是你的目标,所以没有发布答案,因为我不想贬低你想要完成的事情。祝你好运。tnx@SteveGreene&AaronLS。如果没有其他方法,我将通过覆盖SaveChanges或修改房间控制器来改变商业模式。我承认@AaronLS在他对你的问题的评论中所说的话,但是-如果其他学生没有被加载,你必须查询数据库以检查计数,这是需要记住的。TNX@jj,我将尝试您的IValidatableObject解决方案。在您的评论中,我可以从“学生”中添加对“房间”的引用。那你怎么办。tnx@Dudi:在学生中,您可以添加属性public virtual Room{get;set;}和/或public int RoomID{get;set;}。有一个例子。然后您可以使用这些属性检查房间的学生人数。
public virtual  Student Student-01 {get;set;}
public virtual  Student Student-02 {get;set;}
....
public virtual  Student Student-20 {get;set;}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;

namespace College.Models
{
    public class Student : IValidatableObject
    {
        [Key]
        public int StudentID { get; set; }
        public string Name { get; set; }
        public virtual Room Room { get; set; }

        //validation:
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {

            if (Room.Students.Count() > 20)
                yield return new ValidationResult("Too many students in class", new[] { "RoomId" });
        }


    }

public class Room
{
    public Room()
    {
        Students = new List<Student>();
    }

    [Key]
    public int RoomID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Student> Students {get;set;}

}

}
// POST: Rooms/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(Room room)
{
    try
    {

        if (ModelState.IsValid)
        {
            db.Entry(room).State = EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        return View(post);

    }
    catch (DbEntityValidationException ex)
    {
        var error = ex.EntityValidationErrors.First().ValidationErrors.First();
        this.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
        return View(room);
    }

}
@Html.ValidationMessageFor(model => model.RoomId, "", new { @class = "text-danger" })