在使用它们的范围内考虑“模型”会有所帮助。创建视图的逻辑需要传递信息以最终创建数据。这可能会导致与数据模型的一对一关系,或者负责创建多个数据模型。视图的模型不必是数据模型,可以说在大多数情况下它应该是视图模型,它是一个简单的、可序列化的 POCO,仅中继视图和相关操作所需的尽可能多的信息。这使得服务器和客户端之间的通信紧凑而高效,并减少了从数据库中提取的数据量。当经常使用实体以使操作正常工作时,您最终必须为实体上未显示的值定义隐藏字段,以便发送回操作的序列化表单数据或“实体”相当完整足够的。随着应用程序的发展和增加客户端和服务器之间的消息大小,这最终会导致错误,并且会公开更多关于您的域的信息,而不是客户端可能知道的。
对于非常简单的小型操作,您甚至可能不需要视图模型,只需将值作为参数传递给操作即可。例如在删除操作的情况下,我们不需要发送整个实体来告诉服务器删除它,我们可以只传递 PK 字段。
因此,对于像创建患者这样的事情,我们可以定义一个 CreatePatientViewModel:
[Serializable]
public class CreatePatientViewModel
{
public string Name { get; set; }
public string Contact { get; set; }
public string Diagnosis { get; set; }
}
然后在视图中我们在控制器上调用 CreatePatient 操作的地方,我们将匹配的值打包为 JSON。即作为 Ajax 调用的一部分:
data: {Name = name, Contact = contact, Diagnosis = diagnosis }
这些值是从相关输入控件等中提取的。
从该视图模型中,我们可以在操作中组合新的 Patient 和相关的 Diagnosis 实体。
public JsonResult CreatePatient(CreatePatientViewModel patientVM)
{
if (patientVM == null)
throw new ArgumentNullException("patientVM");
using (var context = new AppDbContext())
{
var patient = new PatientModel
{
Name = patientVM.Name,
Contact = patientVM.Contact,
Diagnosis = new DiagnosisModel
{
DiagnosisName = patientVM.Diagnosis
}
};
context.Patients.Add(patient);
context.SaveChanges();
return Json(new { success = true; patientId = patient.PatientId });
}
}
代码逻辑可以采取措施检查重复数据或对提供的值执行验证。显然,我们会添加异常处理来处理任何错误并通知用户任何问题。在此示例中,该操作返回一个 JSON 对象以指示调用是否成功并传回新的患者 ID。或者,您可以传回 ViewResult 以刷新页面等。只有 3 个参数,您可以将这 3 个值作为参数传递。系统趋于发展,因此定义视图模型通常比附加参数更简洁。
在我们可能想要创建一个与现有其他实体有关联的新实体的情况下,例如注意到他们从下拉列表中选择的诊所的家庭医生,我们会发送类似 DoctorId 的信息从他们的选择中提取,而不是担心传递整个 Doctor 实体。 CreatePatient 操作可以验证提供的医生 ID 是否有效,并从 DbContext 中解析出 Doctor 实体以关联到新的 Patient 实体。
using (var context = new AppDbContext())
{
var doctor = context.Doctors.Single(x => x.DoctorId == patientVM.FamilyDoctorId);
var patient = new PatientModel
{
Name = patientVM.Name,
Contact = patientVM.Contact,
Doctor = doctor,
Diagnosis = new DiagnosisModel
{
DiagnosisName = patientVM.Diagnosis
}
};
context.Patients.Add(patient);
context.SaveChanges();
这假设家庭医生选择是强制性的,并提供提供的医生 ID 是有效的固有验证。