C# MVC EF5 delete relationships

Asked

Viewed 1,013 times

0

Hello, I am developing an application using C# MVC and EF5 and I have the following problem: I have a customer group management screen, in this group I can insert and remove customers, I use a relationship table between clients and groups called client_group_client (obviously it has relationship with the client_group table), when I add a customer to this group, I insert their information into a table on the screen: inserir a descrição da imagem aqui

The code of each of these lines goes something like this:

<button class="btn_remove">Remover</button> <input name="client_group_client[0].id_client" type="hidden" value="3">

<input name="client_group_client[0].id" type="hidden" value="3">

<input name="client_group_client[0].status" type="hidden" value="1">

<input name="client_group_client[0].datetime_inclusion" type="hidden" value="15/07/2014 10:06:24">

Cliente 3

if I insert a new account and save, will insert a record in the bank, until then it is working, the problem is when I try to remove one of these records, the object passed to the comes only with active relations on the screen, I don’t know which one was removed so I could remove it from the bank. Does anyone have any idea how to do this?

controller Clientgroupcontroller:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(client_group client_group, string actionSubmit, string urlReferrer)
    {
        repository.BeforeUpdate(client_group);
        if (!repository.Save())
        {
            setFlash("danger", repository.GetHtmlErrors());
            return View("~/Views/Person/ClientGroup/Edit.cshtml", client_group);
        }

        setFlash("success", I18n.T("Alert","RegisterSaveSucess"));


        if (actionSubmit == "saveAndBack")
            return Redirect(urlReferrer);
        else
            return View("~/Views/Person/ClientGroup/Edit.cshtml", client_group);
    }

Repository class (created by me to process data before/after modifying):

public override bool BeforeUpdate(client_group obj)
    {
        foreach (client_group_client register in obj.client_group_client)
        {
            register.id_client_group = obj.id;

            if (register.datetime_inclusion == null)
            {
                register.datetime_inclusion = DateTime.Now;
                register.status = client_group_client.ACTIVE;
                dbContext.Entry(register).State = EntityState.Added;
            }
            else
            {
                dbContext.Entry(register).State = EntityState.Modified;
            }
        }

        return base.BeforeUpdate(obj);
    }
  • You are sending to Action of exclusion for which Controller?

  • Gypsy Morrison Mendez, edited the question, see if it helps

  • Why call the controller client_group where you are excluding an association client_group_client?

  • @Gypsy, because the canvas (CRUD) is related to the client_group, within it I make group relationship with customers

  • There is no need for this standardization. Each association has a <form>, right? I deduced this because you use one button for each. You can call another controller that excludes for you. It is even more correct from the point of view of the application design.

  • @Gypsy, did not understand its placement, is all within the same <form>

  • Got it. I think this is the tricky one. I’m going to suggest an answer.

Show 2 more comments

2 answers

0

One of the ways to solve it is:

  • Get the group’s customer list as it is in your database (just so you know which one has been removed);

  • Change/Update the customer list as you remove/edit the group’s clients and save

Example:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(client_group client_group, string actionSubmit, string urlReferrer)
{        
    //Obter a lista de clientes do grupo como está na sua base de dados
    var grupo = repository.ObterGrupoPorId(client_group.IdGroup);
    //Diferença entre as listas para você alterar/atualizar a lista de clientes
    var clientesPosEdicao = ObterClientesInformadosUsuario(client_group).Except(grupo.Clientes).ToList();
    //Alterar/Atualizar a lista de clientes do grupo
    grupo.Clientes = clientesPosEdicao;
    //restante de código desejado para salvar, redirecionar, etc.
}

Note: Code not tested

  • I believe it would work, but if possible I would prefer not to have to perform a new database search

  • Renan, I tested a variation of your code by putting this in the Beforeupdate: client_group group = this. Find(obj.id); List<client_group_client> clients = group.client_group_client.Except(obj.client_group_client). Tolist(); foreach (client_group_client Register in clients) { dbContext.Entry(Register). State = Entitystate.Deleted; } but gave the following error: An Object with the same key already exists in the Objectstatemanager. The Objectstatemanager cannot track Multiple Objects with the same key.

  • @Andrehodon example code is unrelated to the Beforeupdate method. The example tries to help in "which customer has been removed so you can remove from the bank". This error is EF specific (where I can’t help you much) and may be due to some object (group or client) is already loaded in your context. See https://mastigado.wordpress.com/tag/an-object-with-the-same-key-already-exists-in-the-objectstatemanager-the-objectstatemanager-cannot-track-multiple-objects-with-the-same-key/ and this link http://msdn.microsoft.com/en-US/data/jj592676.

0


I believe the fact that you’re sending an instruction to the Controller to which the association record belongs may be the complicator.

The solution I’m going to pass is possibly quite different from what you’ve imagined, but it’s the simplest from the point of view of MVC architecture.

Here’s what I’d do:

1. Change the Remove button to a normal link

@Html.ActionLink("Remover", "Delete", "ClientGroupClient", new { id = client_group_client[0].id })

2. User a Delete Action in the Clientgroupclient Controller, instead of the Clientgroup Controller

// Esta Action pode abrir uma View de confirmação, mas é opcional.
// Você pode implementar apenas a Action mais abaixo.
public ActionResult Delete(int id)
{
    var clientGroupClient = dbContext.ClientGroupClients.Single(x => x.Id == id);
    return View(clientGroupClient);
}

Notice that to call this Action, it needs to be a requisition POST. This is not required, but I usually use this to ensure that there is a confirmation for deletion of the record, just for security.

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
    var clientGroupClient = dbContext.ClientGroupClients.Single(x => x.Id == id);
    var clientGroupId = clientGroupClient.ClientGroupId;

    dbContext.ClientGroupClients.Remove(clientGroupClient);
    dbContext.SaveChanges();
    return RedirectToAction("Details", "ClientGroups", new { id = clientGroupId });
}
  • 1

    really is a very different proposal than I had imagined, I thought of something that would delete the records at the same time that saved the changes made in the client_group table, but I will follow your advice, thank you very much

  • 1

    @Andrehodon this form proposed by the Gypsy is much better! In my answer I did not want to change its way of doing, but follow this msm proposal. But, note q still you need to search the information in the bank to know which customer to remove.

  • @Renan was different from what I intended at first but it really worked, thank you very much

Browser other questions tagged

You are not signed in. Login or sign up in order to post.