I have repeatedly and repeatedly asked how to bind N to N here in site . Anyway, I'm going to work this out for you better.
There are two ways to define N to N association in the Entity Framework: via Fluent API , which is a more ingrained form because it does not allow for greater configuration of the assoatva table, or by manual mapping, which gives a little more work but is better.
First, define a Model like this:
public class UsuarioEmpresa
{
[Key]
public int UsuarioEmpresaId { get; set }
[Index("IUQ_UsuarioEmpresa_UsuarioId_EmpresaId", IsUnique = true, Order = 1)]
public int UsuarioId { get; set; }
[Index("IUQ_UsuarioEmpresa_UsuarioId_EmpresaId", IsUnique = true, Order = 2)]
public int EmpresaId { get; set; }
// Você pode definir mais campos aqui
public virtual Usuario Usuario { get; set; }
public virtual Empresa Empresa { get; set; }
}
[Index]
, introduced in this form from the Entity Framework 6.1.0, guarantees the uniqueness of the associative register. Additional validations may be required in the application to avoid extraneous errors of key duplication for the user.
With this, I'm assuming you have two other Models in your application with something like this:
public class Usuario
{
[Key]
public int UsuarioId { get; set; }
// Outras propriedades aqui
public virtual ICollection<UsuarioEmpresa> EmpresasUsuario {get; set;}
}
public class Empresa
{
[Key]
public int EmpresaId { get; set; }
// Outras propriedades aqui
public virtual ICollection<UsuarioEmpresa> EmpresaUsuarios {get; set;}
}
Once this is done, we can either write a Controller or generate a path Scaffolding :
using System.Data.Entity;
using System.Threading.Tasks;
using System.Net;
using System.Web.Mvc;
using SeuProjeto.Models;
namespace SeuProjeto.Controllers
{
public class UsuariosEmpresasController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: UsuariosEmpresas
public async Task<ActionResult> Index()
{
var usuarioEmpresas = db.UsuarioEmpresas.Include(u => u.Empresa).Include(u => u.Usuario);
return View(await usuarioEmpresas.ToListAsync());
}
// GET: UsuariosEmpresas/Details/5
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
UsuarioEmpresa usuarioEmpresa = await db.UsuarioEmpresas.FindAsync(id);
if (usuarioEmpresa == null)
{
return HttpNotFound();
}
return View(usuarioEmpresa);
}
// GET: UsuariosEmpresas/Create
public ActionResult Create()
{
ViewBag.EmpresaId = new SelectList(db.Empresas, "EmpresaId", "Nome");
ViewBag.UsuarioId = new SelectList(db.Usuarios, "UsuarioId", "Nome");
return View();
}
// POST: UsuariosEmpresas/Create
// 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 async Task<ActionResult> Create([Bind(Include = "UsuarioEmpresaId,UsuarioId,EmpresaId")] UsuarioEmpresa usuarioEmpresa)
{
if (ModelState.IsValid)
{
db.UsuarioEmpresas.Add(usuarioEmpresa);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.EmpresaId = new SelectList(db.Empresas, "EmpresaId", "Nome", usuarioEmpresa.EmpresaId);
ViewBag.UsuarioId = new SelectList(db.Usuarios, "UsuarioId", "Nome", usuarioEmpresa.UsuarioId);
return View(usuarioEmpresa);
}
// GET: UsuariosEmpresas/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
UsuarioEmpresa usuarioEmpresa = await db.UsuarioEmpresas.FindAsync(id);
if (usuarioEmpresa == null)
{
return HttpNotFound();
}
ViewBag.EmpresaId = new SelectList(db.Empresas, "EmpresaId", "Nome", usuarioEmpresa.EmpresaId);
ViewBag.UsuarioId = new SelectList(db.Usuarios, "UsuarioId", "Nome", usuarioEmpresa.UsuarioId);
return View(usuarioEmpresa);
}
// POST: UsuariosEmpresas/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 async Task<ActionResult> Edit([Bind(Include = "UsuarioEmpresaId,UsuarioId,EmpresaId")] UsuarioEmpresa usuarioEmpresa)
{
if (ModelState.IsValid)
{
db.Entry(usuarioEmpresa).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.EmpresaId = new SelectList(db.Empresas, "EmpresaId", "Nome", usuarioEmpresa.EmpresaId);
ViewBag.UsuarioId = new SelectList(db.Usuarios, "UsuarioId", "Nome", usuarioEmpresa.UsuarioId);
return View(usuarioEmpresa);
}
// GET: UsuariosEmpresas/Delete/5
public async Task<ActionResult> Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
UsuarioEmpresa usuarioEmpresa = await db.UsuarioEmpresas.FindAsync(id);
if (usuarioEmpresa == null)
{
return HttpNotFound();
}
return View(usuarioEmpresa);
}
// POST: UsuariosEmpresas/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int id)
{
UsuarioEmpresa usuarioEmpresa = await db.UsuarioEmpresas.FindAsync(id);
db.UsuarioEmpresas.Remove(usuarioEmpresa);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
E Views (also by Scaffolding ):
Create.cshtml
@model SeuProjeto.Models.UsuarioEmpresa
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>UsuarioEmpresa</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.UsuarioId, "UsuarioId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("UsuarioId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.UsuarioId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmpresaId, "EmpresaId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("EmpresaId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.EmpresaId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Delete.cshtml
@model SeuProjeto.Models.UsuarioEmpresa
@{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>UsuarioEmpresa</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Empresa.Nome)
</dt>
<dd>
@Html.DisplayFor(model => model.Empresa.Nome)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Usuario.Nome)
</dt>
<dd>
@Html.DisplayFor(model => model.Usuario.Nome)
</dd>
</dl>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
@Html.ActionLink("Back to List", "Index")
</div>
}
</div>
Details.cshtml
@model SeuProjeto.Models.UsuarioEmpresa
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
<h4>UsuarioEmpresa</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Empresa.Nome)
</dt>
<dd>
@Html.DisplayFor(model => model.Empresa.Nome)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Usuario.Nome)
</dt>
<dd>
@Html.DisplayFor(model => model.Usuario.Nome)
</dd>
</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.UsuarioEmpresaId }) |
@Html.ActionLink("Back to List", "Index")
</p>
Edit.cshtml
@model SeuProjeto.Models.UsuarioEmpresa
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>UsuarioEmpresa</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.UsuarioEmpresaId)
<div class="form-group">
@Html.LabelFor(model => model.UsuarioId, "UsuarioId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("UsuarioId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.UsuarioId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmpresaId, "EmpresaId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("EmpresaId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.EmpresaId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Index.cshtml
@model IEnumerable<SeuProjeto.Models.UsuarioEmpresa>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Empresa.Nome)
</th>
<th>
@Html.DisplayNameFor(model => model.Usuario.Nome)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Empresa.Nome)
</td>
<td>
@Html.DisplayFor(modelItem => item.Usuario.Nome)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.UsuarioEmpresaId }) |
@Html.ActionLink("Details", "Details", new { id=item.UsuarioEmpresaId }) |
@Html.ActionLink("Delete", "Delete", new { id=item.UsuarioEmpresaId })
</td>
</tr>
}
</table>
Having this, just modify Controller and Views to get the desired behavior.