Edit object, with related objects

Asked

Viewed 167 times

2

I Have an Object Cliente relating to two other objects.

[Table("Cliente")]
public class Cliente
{
    [StringLength(100, ErrorMessage = "Este campor permite apenas 100 caracteres"), Required]
    public String Nome { get; set; } ...

    public virtual Titulo Titulo { get; set; }

    public virtual ICollection<Dependentes> Dependentes { get; set;}
}

That relates to Titulo

[Table("Titulo")]
public class Titulo
{
    [Key, ForeignKey("Cliente")]
    public Guid TituloId { get; set; }

    public DateTime DataCadastro { get; set; }

    public DateTime DataExpiracao { get; set; }

    //Relacionamento tabela Cliente
    public virtual Cliente Cliente { get; set; }
}

And with Dependentes

[Table("Dependentes")]
public class Dependentes
{
    public Guid DependentesId { get; set; }
    public Guid ClienteId { get; set; }

    public String Nome { get; set; }

    public virtual Cliente Cliente { get; set; }
}

I am trying to make the Editing of this object, and those who relate to it, using the following method in my controller. I left some comments, because it was in some ways that I tried.

[HttpPost]
public async Task<ActionResult> Editar(Cliente cliente)
{
    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
       var cli = await db.Clientes
                                .Include(c => c.Titulo)
                                .Include(d => d.Dependentes)
                                .FirstOrDefaultAsync(c => c.ClienteId == cliente.ClienteId);

        // Dependentes Originais
        var denpendentesOriginais = await db.Dependentes.AsNoTracking().Where(ct => ct.Cliente.ClienteId == cli.ClienteId).ToListAsync();
        if (cliente.Dependentes != null)
        {
            // Dependentes Excluídos
            foreach (var dependenteOriginal in denpendentesOriginais)
            {
                if (!cliente.Dependentes.Any(dp => dp.DependentesId == dependenteOriginal.DependentesId))
                {
                    var dependenteExcluido = await db.Dependentes.SingleAsync(dp => dp.DependentesId == dependenteOriginal.DependentesId);
                    db.Dependentes.Remove(dependenteExcluido);
                    await db.SaveChangesAsync();
                }
            }

            // Dependentes Inseridos ou Alterados
            foreach (var dependente in cliente.Dependentes)
            {
                if (!denpendentesOriginais.Any(dp => dp.DependentesId == dependente.DependentesId))
                {
                    // Dependente não existe ainda. Inserir.
                    dependente.ClienteId = cliente.ClienteId;
                    db.Dependentes.Add(dependente);
                }
                else
                {
                    // Dependente já existe. Marcar como alterado.
                    db.Entry(dependente).State = EntityState.Modified;
                }

                await db.SaveChangesAsync();
            }
        }
            ViewBag.PossibleUsuarios = db.Users;
            scope.Complete();
            return View(cliente);
        }
    }

In this code snippet,

else
{
   // Dependente já existe. Marcar como alterado.
   db.Entry(dependente).State = EntityState.Modified;
}

have a Mistake:

Attaching an Entity of type 'Vendadetitulos.Models.Dependentes' failed because other Entity of the same type already has the same Primary key value. This can happen when using the 'Attach' method or Setting the state of an Entity to 'Unchanged' or 'Modified' if any entities in the Graph have Conflicting key values. This may be because some entities are new and have not yet Received database-generated key values. In this case use the 'Add' method or the 'Added' Entity state to track the Graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

I’m not sure if I implemented it the right way, I imagine not, or if something was missing.

How can I do this procedure?

There’s a better way to solve this problem than what I’m doing?

1 answer

3

This code is useless and is causing your error:

    Titulo titulo = await db.Titulos.SingleAsync(t => t.TituloId == cli.ClienteId);
    db.Entry(titulo).State = EntityState.Modified;
    await db.SaveChangesAsync();

Here you select Titulo from the bank, mark it as altered and saved. Entity Framework did not notice any change and the object is observed throughout the rest of the execution.

I also did not understand what this if has to do with the logic of dependents:

if (cliente.Titulo != null) { ... }

That logic is not good:

        if (!cliente.Dependentes.Any(ct => ct.ClienteId == dependenteOriginal.ClienteId))
        {
            var dependenteExcluido = db.Dependentes.Single(ct => ct.DependentesId == dependenteOriginal.Cliente.ClienteId);
            db.Dependentes.Remove(dependenteExcluido);
            await db.SaveChangesAsync();
        }

Here you are not necessarily selecting the dependent by the key of it, which can bring another dependent and delete it improperly. The right thing would be:

        if (!cliente.Dependentes.Any(dp => dp.DependenteId == dependenteOriginal.DependenteId))
        {
            var dependenteExcluido = db.Dependentes.Single(dp => dp.DependenteId == dependenteOriginal.DependenteId);
            db.Dependentes.Remove(dependenteExcluido);
            await db.SaveChangesAsync();
        }

Same thing on the bottom:

    // Dependentes Inseridos ou Alterados
    foreach (var dependente in cliente.Dependentes)
    {
        if (!denpendentesOriginais.Any(dp => dp.DependenteId == dependente.DependenteId))
        {
            // Dependente não existe ainda. Inserir.
            dependente.ClienteId = cliente.ClienteId;
            db.Dependentes.Add(dependente);
        }
        else
        {
                // Dependente já existe. Marcar como alterado.
            db.Entry(dependente).State = EntityState.Modified;
        }

        await db.SaveChangesAsync();
    }

Remove this part too, which is only getting in the way:

var cli = await db.Clientes
                            .Include(c => c.Titulo)
                            .Include(d => d.Dependentes)
                            .FirstOrDefaultAsync(c => c.ClienteId == cliente.ClienteId);

Browser other questions tagged

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