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

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

问题描述

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



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



有关如何做的想法?我已经阅读了这个是



修改



您的模型不是真正的多对多关系。你有两个一对多的关系。通常不需要 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 = selected Company .CompanyId};
_context.Companies.Attach(company);

var subscriptionByCompany = new SubscriptionByCompany
{
公司=公司
};

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天全站免登陆