我正在为项目制作互联网课程计划申请表。课程计划是根据以下模型构建的(使用Database First方法中的Entity Framework生成):
public partial class Subject
{
public int Id { get; set; }
public string Hour { get; set; }
public string Name { get; set; }
public int DayId { get; set; }
[Required]
public int PlanId { get; set; }
public virtual Day Day { get; set; }
public virtual Plan Plan { get; set; }
}
public partial class Plan
{
public Plan()
{
this.Przedmiot = new HashSet<Subjects>();
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Subject> Subject { get; set; }
}
我在一个视图中显示两个模型没有问题,但我似乎无法弄清楚如何在创建新计划时将两个模型发布到数据库。我希望我的View看起来像这样:
所以我的问题是这里最好的方法是什么,如何在数据库的Plan表中创建一条记录,并在这一个视图中链接到它的许多主题记录。
编辑: 代码与我的显示按要求查看(省略了不必要的部分,因为它相当长):
@model IEnumerable<Lesson_plan.DAL.Subject>
<table style="border: 1px solid black; margin: 40px; width: 100%;">
<tr>
<th>Hours</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
@{
if (Model != null)
{
var r = 1;
var t = 1;
List<string> hours = new List<string>();
foreach (var subject in Model)
{
if (!hours.Contains(subject.Hour))
{
<tr>
<td>
<textarea>
@Html.DisplayFor(modelItem => subjest.Hour)
@{ hours.Add(subject.Hour); }
</textarea>
</td>
<td>
<textarea>
@foreach (var subjectName in Model)
{
if (subjectName.Day.DayOfTheWeek.Equals("Monday") &&
subject.Hour.Equals(subjetName.Hour))
{
@Html.DisplayFor(modelItem => subject.Name)
}
}
</textarea>
</td>
//and so on for every day
}
</tr>
r++;
}
}
}
}
</table>
我的Controller类的代码(我使用Create方法进行了一些实验,但我在这里发布了原始方法):
namespace Lesson_plan.Controllers
{
public class PlansController : Controller
{
private readonly LessonPlanEntities db = new LessonPlanEntities();
// GET: Plans
public ActionResult Index()
{
var plans = db.Plan.ToList();
return View(plans);
}
// GET: Plans/Details/5
public ActionResult Details(int? id)
{
if (id == null)
return Create();
var subjects = db.Subject.
Where(x => x.PlanId == id).
OrderByDescending(x => x.Hour).ToList();
if (subjects.Count > 0)
ViewBag.Title = subjects[0].Plan.Name;
return View(subjects);
}
// GET: Plans/Create
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Plan plan)
{
if (ModelState.IsValid)
{
db.Plan.Add(plan);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(plan);
}
// GET: Plans/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var plan = db.Plan.Find(id);
if (plan == null)
return HttpNotFound();
return View(plan);
}
// POST: Plans/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([Bind(Include = "Id,Nazwa")] Plan plan)
{
if (ModelState.IsValid)
{
db.Entry(plan).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(plan);
}
// GET: Plans/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var plan = db.Plan.Find(id);
if (plan == null)
return HttpNotFound();
return View(plan);
}
// POST: Plans/Delete/5
[HttpPost]
[ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
var plan = db.Plan.Find(id);
db.Plan.Remove(plan);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
db.Dispose();
base.Dispose(disposing);
}
}
}
EDIT2 使用表单创建视图的代码:
@model Lesson_plan.DAL.Plan
@using (Html.BeginForm("Create", "Plans"))
{
<div>
@Html.LabelFor(plan => plan.Name)<br/>
@Html.TextAreaFor(plan => plan.Name)
</div>
<table style="border: 1px solid black; margin: 40px; width: 100%;">
<tr>
<th>Hours</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
@{
for (int i = 0; i < 7; i++)
{
<tr>
//what sould i put here ?
<td><textarea></textarea></td>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
<th><textarea></textarea></th>
</tr>
}
}
</table>
<p>
<a type="button" class="btn btn-info" href=@Url.Action("Index")>Back</a>
<input type="submit" value="Create"/>
</p>
}
答案 0 :(得分:3)
最好的方法是设计一个ViewModel类,它可以保存您的表单上需要提交的所有数据,包括计划和/或主题。
在接收此ViewModel的Action Method中,您可以分离数据,并根据该数据执行将数据存储在数据库中所需的任何插入和/或更新。
只有Controller应该知道您的数据库类。 ViewModel和Database对象之间的所有映射都应该由控制器完成,View不应该受到打扰或妨碍。
答案 1 :(得分:0)
通过将多个模型组合到视图模型中,可以将多个模型发送到视图。但是,你的问题似乎有所不同,所以这里有很长的答案:
至于数据库设计问题,我假设您正在使用关系存储,并且一个主题可以存在于多个计划中,因此应该有多对多应用程序。您可以阅读有关主题here的更多信息。
对于您的网络应用,您通常只需创建一个包含所需模型的ViewModel。如果您没有详细说明您的问题,那将是正确的答案。但是,在您的情况下,您的两个“模型”类已经链接,因此您的模型可以只是一个计划。
由于我假设您正在使用EF6(根据您生成的课程),您的计划主题将与计划一起发布。
我要做的是使用singleton在应用程序的某个位置缓存当前存在的主题,然后在回发时,您应该遍历计划的缓存主题,检查它们是否已存在于您的数据库中。如果他们不这样做 - 先插入它们,如果他们这样做 - 只需将它们添加到计划中的ICollection中。那你应该知道如何使用EF插入计划。
在此过程中可能会有更多的障碍,但你可以提出有关这些问题的新问题 - 你现在的问题太宽泛了。
我正在努力帮助你获得一些有用的东西,尽管它可能并不理想。一旦你开始工作,我建议阅读在哪里放置业务逻辑(以及如何保持你的控制器小)。 This文章可能是一个好的开始。
我建议的另一件事是将您的数据访问保留在单独的层中。 Goodle“3层架构”并在存储库模式上检查this video。
祝你好运!**发布OP-edit **
好的,看看你的代码似乎有很多问题,你可能想要分成多个问题。这是一个开始:
Controller
的{{1}}上显示操作方法的版本。对于旧版本,我建议使用asp {mcc核心的this教程和this。如果您想要“编辑”和“显示”视图的不同页面,只需创建单独的页面,但在创建时,您将需要一个表单。 **编辑2 **
现在看到您的计划创建代码,您似乎已经正确地读到[Post]
是创建可以发布到服务器的输入的方式。
但是,您只是将它用于您的计划名称。
不使用下面的textarea(我假设这些是主题名称),而是使用类似
的内容@Html.TextAreaFor(plan => plan.Name)
假设您作为模型传递给视图的计划有任何主题,这将是列出它们并使其可编辑的方式。
现在,您似乎希望根据星期几将它们分开,因此您可能需要进行一些过滤,例如:
@for(int i = 0; i < plan.Subject.Count(); i++)
{
@Html.TextAreaFor(plan => plan.Subject[i].Name)
}
将其粘贴到七列中的每一列中。现在,这将为已经存在的每个主题创建textareas。
至于在视图上动态创建新的,请参阅上面的第3点。如果你还没有任何科目,可以在你的数据库中创建一些假的,这样你就可以在客户端渲染一些并查看它们的源代码,然后按照我在#3中链接的文章。