MVC 4 - 多对多关系和复选框 [英] MVC 4 - Many-to-Many relation and checkboxes

查看:178
本文介绍了MVC 4 - 多对多关系和复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET MVC 4和Entity Framework。在我的数据库中,我有一个表订阅,表示对公共交通的订阅。这个订阅可以提供访问几个公共交通公司(所以订阅可以有1,2,3 ...公司),那么这是一个多对多的关系,这些表(我有它们之间的中间表)。



我想允许通过一个页面创建订阅,该页面将包含订阅的字段 和可用公司的复选框。每个复选框代表一个现有的公司(存储在我的数据库中的公司)。



有关如何做的任何想法?我阅读了这个是编辑



编辑



你的模型并不是一个多对多的关系。您有两个一对多关系。不需要 PublicTransportSubscriptionByCompany 实体 - 通常。如果您在 Id_PublicTransportSubscription,Id_PublicTransportCompany 中创建一个复合主键,并删除id列 Id_PublicTransportSubscriptionByCompanyId 此表模式作为多对多关系,并在每个实体中为订阅和公司创建一个集合,并且它将不为链接表创建实体。



如果您不想因某些原因更改模式,您必须更改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);
}


I'm working with ASP.NET MVC 4 and Entity Framework. In my database, I have a table Subscription which represents a subscription to public transports. This subscription can provide access to several public transport companies (so a subscription could have 1, 2, 3, ... companies) then it is a Many-to-Many relation between these tables (I have an intermediate table between them).

I want to allow the creation of a subscription throught a page which will contain a field Amount of the subscription and the available companies by checkboxes. Every checkbox represents an existing company (a company stored in my database).

Any idea about how to do that? I've read this ASP.NET MVC Multiple Checkboxes but it was not really helpful.

EDIT : Here is my tables diagram.

解决方案

You start with two view models. The first one which represents a selected company...

public class CompanySelectViewModel
{
    public int CompanyId { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

...and the second one for the subscription to create:

public class SubscriptionCreateViewModel
{
    public int Amount { get; set; }
    public IEnumerable<CompanySelectViewModel> Companies { get; set; }
}

Then in the SubscriptionControllers GET action you load the companies from the database to initialize the view model:

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

Now, you have a strongly typed view for this action:

@model SubscriptionCreateViewModel

@using (Html.BeginForm()) {

    @Html.EditorFor(model => model.Amount)

    @Html.EditorFor(model => model.Companies)

    <input type="submit" value="Create" />
    @Html.ActionLink("Cancel", "Index")
}

To get the company checkboxes rendered correctly you introduce an editor template. It must have the name CompanySelectViewModel.cshtml and goes into the folder Views/Subscription/EditorTemplates (create such a folder manually if it doesn't exist). It's a strongly typed partial 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 is added as hidden field to preserve the name during a POST.

Obviously you have to style the views a bit more.

Now, your POST action would look like this:

[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);
}

Instead of using Attach you can also load the company first with var company = _context.Companies.Find(selectedCompany.CompanyId);. But with Attach you don't need a roundtrip to the database to load the companies to be added to the collection.

(Edit 2: In this answer is a continuation for the Edit actions and views with the same example model.)

Edit

Your model is not really a many-to-many relationship. You have two one-to-many relationships instead. The PublicTransportSubscriptionByCompany entity is not needed - normally. If you have a composite primary key in that table made of Id_PublicTransportSubscription, Id_PublicTransportCompany and remove the id column Id_PublicTransportSubscriptionByCompanyId EF would detect this table schema as a many-to-many relationship and create one collection in each of the entities for subscription and company and it would create no entity for the link table. My code above would apply then.

If you don't want to change the schema for some reason you must change the POST action like so:

[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);
}

这篇关于MVC 4 - 多对多关系和复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆