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