11

我有一个 ViewModel,它由三个实体连接,以将所有实体的数据获取到一个视图表单中。虽然我成功地实现了相同的。但我不知道如何编辑并将数据保存回数据库。我的模型类是通过一对一的关系加入的。

我的模型是:

public class Doctor
{
    public int DoctorId { get; set; }
    public string Name { get; set; }
    public string Speciality { get; set; }

    public virtual DoctorAddress DoctorAddress { get; set; }
    public virtual DoctorCharge DoctorCharge { get; set; }
    public virtual DoctorAvailablity DoctorAvailablity { get; set; }

}

public class DoctorAddress
{
    public string Address { get; set; }
    public string City { get; set; }
    public int DoctorId { get; set; }

    public virtual Doctor Doctor { get; set; }
}

public class DoctorCharge
{
    public decimal OPDCharge { get; set; }
    public decimal IPDCharge { get; set; }
    public int DoctorId { get; set; }

    public virtual Doctor Doctor { get; set; }
}

我的视图模型是:

public class DoctorViewModel
    {
        public Doctor Doctor { get; set; }
        public DoctorAddress DoctorAddress { get; set; }
        public DoctorCharge DoctorCharge { get; set; }

    }

我的控制器是:

public ActionResult Index()
    {
        var model = from t1 in db.Doctors
                    join d in db.DoctorAddress on t1.DoctorId equals  d.DoctorId into listi
                    join dc in db.DoctorCharges on t1.DoctorId equals dc.DoctorId into listj

                    from d in listi.DefaultIfEmpty()
                    from dc in listj.DefaultIfEmpty()

                    select new DoctorDetailsViewModel.DoctorViewModel { Doctor = t1, DoctorAddress = d, DoctorCharge = dc };

        return View(model.ToList());

    }

我的观点是:

@model XXX.DoctorDetailsViewModel.DoctorViewModel

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>Doctor</legend>

    <div class="editor-label">
       Name
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Doctor.Name)
    </div>

    <div class="editor-label">
        OPD Charge
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DoctorCharge.OPDCharge)
    </div>

<div class="editor-label">
        Address
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DoctorAddress.Address)
    </div> <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>}

我的控制器类是:

public ActionResult Create()
    {
        return View();
    }

    //
    // POST: /Doctor/Create

    [HttpPost]
    public ActionResult Create(Doctor doctor)
    {
        if (ModelState.IsValid)
        {
            db.Doctors.Add(doctor);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(doctor);
    }

请帮助我该怎么做。提前致谢。

4

3 回答 3

4

在这里,用于创建:

[HttpPost]
public ActionResult Create(DoctorViewModel model)
{
    if (ModelState.IsValid)
    {
        model.Doctor.DoctorAddress = model.DoctorAddress;
        model.Doctor.DoctorCharge = model.DoctorCharge;
        db.Doctors.Add(doctor);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(doctor);
}
于 2013-08-14T18:58:05.590 回答
4

首先,您使用它真的很好,ViewModels但对于这种特殊情况,可能没有必要,您的Create视图可能如下所示:

@model MvcApplication1.Models.Doctor

//other fields here

<div class="editor-label">
        @Html.LabelFor(model => model.DoctorAddress.Address)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DoctorAddress.Address)
        @Html.ValidationMessageFor(model => model.DoctorAddress.Address)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.DoctorCharge.IPDCharge)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DoctorCharge.IPDCharge)
        @Html.ValidationMessageFor(model => model.DoctorCharge.IPDCharge)
</div>

//other fields here

然后你的Doctor控制器:

[HttpPost]
public ActionResult Create(Doctor doctor)
{
    if (ModelState.IsValid)
    {
        db.Doctors.Add(doctor);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(doctor);
}

Your `Edit` action could then look like this:

[HttpGet]
public ActionResult Edit(int id = 0)
{
    Doctor doctor = db.Doctors.Find(id);
    if (doctor == null)
    {
        return HttpNotFound();
    }
    return View(doctor);
}

[HttpPost]
public ActionResult Edit(Doctor doctor)
{
    if (ModelState.IsValid)
    {
        db.Entry(doctor).State = EntityState.Modified;
        db.Entry(doctor.DoctorAddress).State = EntityState.Modified;
        db.Entry(doctor.DoctorCharge).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(doctor);
}

如果您想保留您的 ViewModel,那么它可能如下所示:

[HttpPost]
public ActionResult Edit(DoctorViewModel doctorViewModel)
{
    if (ModelState.IsValid)
    {
        var doctorAddress = doctorViewModel.DoctorAddress;
        var doctorCharge = doctorViewModel.DoctorCharge;
        var doctor = doctorViewModel.Doctor;
        db.Entry(doctorAddress).State = EntityState.Modified;
        db.Entry(doctorCharge).State = EntityState.Modified;
        db.Entry(doctor).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(doctor);
}
于 2013-08-14T18:39:41.353 回答
2

对于这个答案,我使用Tom Dykstra 的教程指南,在ViewModel上下文中使用 ASP.NET MVC 应用程序中的实体框架实现基本 CRUD 功能。

本教程使用TryUpdateModel(TModel, String, String[])方法调用来更新方法中的单个Student模型Edit

     var studentToUpdate = db.Students.Find(id);

     if (TryUpdateModel(studentToUpdate, "",
           new string[] { "LastName", "FirstMidName", "EnrollmentDate" })) {
           //Save all changes made in this context to the underlying database 
           db.SaveChanges();
           return RedirectToAction("Index");
     }

TryUpdateModel如果更新成功,方法返回true,否则返回falseTryUpdateModel方法调用的第一个参数上方是Student模型(studentToUpdate)。第二个参数是在值提供者中查找值的前缀(空字符串"")。第三个参数是更新的属性列表:”LastName", "FirstMidName", "EnrollmentDate"

作为防止过度发布的最佳实践,您希望编辑页面可更新的字段在 TryUpdateModel 参数中列入白名单

为了使上述适用于DoctorViewModel,还需要使用第二个参数(前缀)。例如Doctor模型:

  Doctor doctorToUpdate = db.Doctors.Find(id);

  bool doctorUpdateSuccess = TryUpdateModel(doctorToUpdate, "Doctor", 
                                new string[] { "Name", "Speciality" });

"Doctor"方法调用需要前缀TryUpdateModel,因为DoctorViewModel使用时找不到Doctor模型的参数。例如,下面的 Watch 窗口显示了在 Visual Studio 中在编辑方法的调试模式下表单值是如何显示的:

在此处输入图像描述

Edit查看下面的代码:

<div class="editor-field">
     @Html.EditorFor(model => model.Doctor.Name)
</div>

创建以下 html:

<div class="editor-field">
    <input class="text-box single-line" id="Doctor_Name" 
     name="Doctor.Name" type="text" value="Foo"/>
</div> 

这是Edit方法的代码DoctorViewModel

[HttpPost, ActionName("Edit")]
public ActionResult EditPost(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    Doctor doctorToUpdate = db.Doctors.Find(id);
    if (doctorToUpdate == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    bool doctorUpdateSuccess = TryUpdateModel(doctorToUpdate, "Doctor", new string[] { "Name", "Speciality" });

    DoctorAddress doctorAddressToUpdate = doctorToUpdate.DoctorAddress;
    if (doctorAddressToUpdate == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    bool doctorAddressUpdateSuccess = TryUpdateModel(doctorAddressToUpdate, "DoctorAddress", new string[] { "Address" });

    DoctorCharge doctorChargeToUpdate = doctorToUpdate.DoctorCharge;
    if (doctorChargeToUpdate == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    bool doctorChargeUpdateSuccess = TryUpdateModel(doctorChargeToUpdate, "DoctorCharge", new string[] { "OPDCharge" });

    // if all models have been successfully updated
    // then save changes to database
    if (doctorUpdateSuccess &&
        doctorAddressUpdateSuccess &&
        doctorChargeUpdateSuccess)
    {
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    DoctorDetailsViewModel.DoctorViewModel viewModel = new DoctorDetailsViewModel.DoctorViewModel();
    viewModel.Doctor = doctorToUpdate;
    viewModel.DoctorAddress = doctorAddressToUpdate;
    viewModel.DoctorCharge = doctorChargeToUpdate;
    return View(viewModel);
}

将ValidateAntiForgeryToken属性添加到代码中以防止跨站点请求伪造也是一个好主意。

更新

我还通过添加属性对模型类进行了一些小改动。这使得更容易找到具有关系的模型:

DoctorAddress doctorAddressToUpdate = doctorToUpdate.DoctorAddress;

DoctorCharge doctorChargeToUpdate = doctorToUpdate.DoctorCharge;

因此下面的模型具有[Key][Key, ForeignKey("Doctor")]属性

public class Doctor
{
    [Key]
    public int DoctorId { get; set; }
    public string Name { get; set; }
    public string Speciality { get; set; }

    public virtual DoctorAddress DoctorAddress { get; set; }
    public virtual DoctorCharge DoctorCharge { get; set; }
    public virtual DoctorAvailability DoctorAvailablity { get; set; }

}

public class DoctorAddress
{
    public string Address { get; set; }
    public string City { get; set; }

    [Key, ForeignKey("Doctor")]
    public int DoctorId { get; set; }
    public virtual Doctor Doctor { get; set; }
}

public class DoctorCharge
{
    public decimal OPDCharge { get; set; }
    public decimal IPDCharge { get; set; }

    [Key, ForeignKey("Doctor")]
    public int DoctorId { get; set; }
    public virtual Doctor Doctor { get; set; }
}

欢迎任何与 ViewModel 更新相关的反馈。最近我在自己的项目中遇到了类似的问题,这就是我用来解决这个问题的方法。我想有其他方法可以处理这个问题。

于 2017-06-10T11:32:26.740 回答