这是我在这里的第一个问题,如果我做错了什么,很抱歉。我在这里没有找到答案。
我需要使用以下元数据构建我的数据库:
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; }
}
每个房间最多可容纳 20 名学生。 它可以是 0 名学生、5 名学生或 20 名学生,但不能更多。
我该怎么做?
注意: 我知道我可以更改行:
public virtual ICollection<Student> Students {get;set;}
像这样:
public virtual Student Student-01 {get;set;}
public virtual Student Student-02 {get;set;}
....
public virtual Student Student-20 {get;set;}
但我正在寻找更优雅的解决方案。
我也知道我可以在房间创建/编辑操作的控制器中控制学生人数
但我只想更改DB(模型),除非没有其他解决方案?
谢谢
这似乎是可以通过EF的验证功能实现的:
- 您可以尝试的一件事是在其中一个班级上实施
IValidatableObject
,以验证学生人数是否低于最大限制。过去,我会从关系的"许多"方面这样做,但你的Student
模型似乎没有参考它的Room
。 - 另一种选择是覆盖
DbContext.ValidateEntity
。
任一情况下,验证都将在调用DbContext.SaveChanges
或DbContext.GetValidationErrors
时发生。
有关实体框架验证的详细信息,可以在 MSDN 上查看此文章。
感谢@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;}
}
}
控制器:
// 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" })