我正在使用 ASP.NET MVC 4 和 Entity Framework 。在我的数据库中,我有一个表订阅,它代表公共(public)交通的订阅。此订阅可以提供对多个公共(public)交通公司的访问(因此订阅可以有 1, 2, 3, ... 公司),那么这些表之间是多对多关系(我有它们之间的中间表)。
我想允许通过一个页面创建订阅,该页面将包含订阅的字段金额以及通过复选框显示的可用公司。每个复选框代表一个现有公司(存储在我的数据库中的公司)。
知道如何做到这一点吗?我读过这个ASP.NET MVC Multiple Checkboxes但这并没有真正的帮助。
编辑:这是我的表格图。
最佳答案
您从两个 View 模型开始。第一个代表选定的公司...
public class CompanySelectViewModel
{
public int CompanyId { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
...以及要创建的订阅的第二个:
public class SubscriptionCreateViewModel
{
public int Amount { get; set; }
public IEnumerable<CompanySelectViewModel> Companies { get; set; }
}
然后在 SubscriptionController
的 GET 操作中,从数据库加载公司以初始化 View 模型:
public ActionResult Create()
{
var viewModel = new SubscriptionCreateViewModel
{
Companies = _context.Companies
.Select(c => new CompanySelectViewModel
{
CompanyId = c.CompanyId,
Name = c.Name,
IsSelected = false
})
.ToList()
};
return View(viewModel);
}
现在,您已拥有此操作的强类型 View :
@model SubscriptionCreateViewModel
@using (Html.BeginForm()) {
@Html.EditorFor(model => model.Amount)
@Html.EditorFor(model => model.Companies)
<input type="submit" value="Create" />
@Html.ActionLink("Cancel", "Index")
}
为了正确呈现公司复选框,您需要引入一个编辑器模板。它必须具有名称 CompanySelectViewModel.cshtml
并进入文件夹 Views/Subscription/EditorTemplates
(如果不存在,请手动创建这样的文件夹)。这是一个强类型的部分 View :
@model CompanySelectViewModel
@Html.HiddenFor(model => model.CompanyId)
@Html.HiddenFor(model => model.Name)
@Html.LabelFor(model => model.IsSelected, Model.Name)
@Html.EditorFor(model => model.IsSelected)
Name
添加为隐藏字段,以在 POST 期间保留名称。
显然,您必须对 View 进行更多样式设置。
现在,您的 POST 操作将如下所示:
[HttpPost]
public ActionResult Create(SubscriptionCreateViewModel viewModel)
{
if (ModelState.IsValid)
{
var subscription = new Subscription
{
Amount = viewModel.Amount,
Companies = new List<Company>()
};
foreach (var selectedCompany
in viewModel.Companies.Where(c => c.IsSelected))
{
var company = new Company { CompanyId = selectedCompany.CompanyId };
_context.Companies.Attach(company);
subscription.Companies.Add(company);
}
_context.Subscriptions.Add(subscription);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
除了使用 Attach
之外,您还可以先使用 var company = _context.Companies.Find(selectedCompany.CompanyId);
加载公司。但使用Attach
,您无需往返数据库即可加载要添加到集合中的公司。
(编辑 2:this answer 中是具有相同示例模型的编辑
操作和 View 的延续。)
编辑
您的模型并不是真正的多对多关系。相反,您有两个一对多关系。通常不需要 PublicTransportSubscriptionByCompany
实体。如果该表中有一个由 Id_PublicTransportSubscription、Id_PublicTransportCompany
组成的复合主键,并删除 id 列 Id_PublicTransportSubscriptionByCompanyId
EF 会将此表架构检测为多对多关系,并且在订阅和公司的每个实体中创建一个集合,并且不会为链接表创建任何实体。我上面的代码将适用。
如果您出于某种原因不想更改架构,则必须更改 POST 操作,如下所示:
[HttpPost]
public ActionResult Create(SubscriptionCreateViewModel viewModel)
{
if (ModelState.IsValid)
{
var subscription = new Subscription
{
Amount = viewModel.Amount,
SubscriptionByCompanies = new List<SubscriptionByCompany>()
};
foreach (var selectedCompany
in viewModel.Companies.Where(c => c.IsSelected))
{
var company = new Company { CompanyId = selectedCompany.CompanyId };
_context.Companies.Attach(company);
var subscriptionByCompany = new SubscriptionByCompany
{
Company = company
};
subscription.SubscriptionByCompanies.Add(subscriptionByCompany);
}
_context.Subscriptions.Add(subscription);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
关于c# - MVC 4 - 多对多关系和复选框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16383494/