Associative Table of Companies and Users, Many for Many

0

I'm starting my studies in ASP.NET and I'm having a hard time making a link between 2 tables of the Many to Many type.

Next I have 2 tables: Company and User, so that a company can have multiple users and at the same time a user can belong to several companies.

In this way I created an intermediate table with foreign key for both.

EX:

[TB_EMPRESA] [PK] COD_EMP, NOME_EMP

[TB_USUARIO] [PK] COD_USU, NOME_USU

[TB_USUARIOEMPRESA] [FK]COD_EMP, [FK]COD_USU

But I'm kind of lost in how to mount the controller and view to insert data.

Does anyone know of any articles or documentation that can help me?

I'm using ASP.NET MVC5 and Entity Framework 6.

    
asked by anonymous 04.03.2017 / 14:55

1 answer

0

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.

    
06.03.2017 / 17:43