Error trying to save information to the database via Entity Framework

Asked

Viewed 122 times

0

My project has the following classes:

public class Manifestacao
{
    public long Id { get; set; }
    public string NumeroChamado { get; set; }
    public virtual Cliente Cliente { get; set; }

    public virtual List<Conteudo> Conteudos { get; set; }
}

public class Conteudo
{
    public long Id { get; set; }
    public string Categoria { get; set; }
    public string SubCategoria { get; set; }
    public string Descricao { get; set; }

    public string Status { get; set; }
    public string Obs { get; set; }
    public string Evidencias { get; set; }

    public long UsuarioAberturaId { get; set; }
    public virtual Usuario UsuarioAbertura { get; set; }

    public long UsuarioFechamentoId { get; set; }
    public virtual Usuario UsuarioFechamento { get; set; }

    public DateTime? DataHoraAbertura { get; set; }
    public DateTime? DataHoraFechamento { get; set; }

    public long ManifestacaoId { get; set; }
    public virtual Manifestacao Manifestacao { get; set; }
}

public class Usuario
{
    public long Id { get; set; }
    public string Apelido { get; set; }
    public string Nome { get; set; }
    public string Categoria { get; set; }
    public string Senha { get; set; }
    public string Status { get; set; }
}

The intention is to take the data entered in a form and save it in the database through the Entity Framework. Some form data is in textboxes and others in datagridview. The user responsible for saving the information is also registered, so far so good. I prompt the objects taking the form information, according to the following code:

        var cliente = new Cliente
        {
            Empresa = txtEmpresaCliente.Text,
            Contato = txtContatoCliente.Text,
            Email = txtEmailCliente.Text,
            Telefone = mskTelefoneCliente.Text,
            Ramal = txtRamalCliente.Text,
            Celular = mskCelularCliente.Text
        };

        List<Conteudo> conteudosDgv = new List<Conteudo>();
        List<string> listaSubCategorias = new List<string>();            

        DateTime dataHoraAbertura = PegaDataHoraUsuario.DataHoraPadrao();

        foreach (DataGridViewRow row in dgvRegistros.Rows)
        {
            Conteudo conteudoLinha = new Conteudo();
            conteudoLinha.Categoria = (string)row.Cells["categoria"].Value;
            conteudoLinha.SubCategoria = (string)row.Cells["subcategoria"].Value;
            conteudoLinha.Descricao = (string)row.Cells["descricao"].Value;
            conteudoLinha.Status = "Novo";
            conteudoLinha.UsuarioAbertura = dalUsuario.GetUsuarioByID(UsuarioLogado.Id);
            conteudoLinha.DataHoraAbertura = dataHoraAbertura;
            conteudosDgv.Add(conteudoLinha);

            listaSubCategorias.Add(conteudoLinha.SubCategoria);
        }
        var manifestacao = new Manifestacao
        {
            Cliente = cliente,
            Conteudos = conteudosDgv,
            NumeroChamado = PegaDataHoraUsuario.nChamado(),
        };
        using (var context = new EFContext())
        {
            context.Manifestacoes.Add(manifestacao);
            context.SaveChanges();
            return true;
        }

When trying to execute the excerpt that saves the data, the error is charged:

System.Data.SqlClient.SqlException: 'Introducing FOREIGN KEY constraint 'FK_dbo.Conteudoes_dbo.Usuarios_UsuarioFechamentoId' on table 'Conteudoes' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint or index. See previous errors.'

I added Foreignkey’s annotations as per RU documentation in the Conteudo class:

    [ForeignKey("UsuarioAbertura")]
    public long UsuarioAberturaId { get; set; }
    public virtual Usuario UsuarioAbertura { get; set; }

    [ForeignKey("UsuarioFechamento")]
    public long UsuarioFechamentoId { get; set; }
    public virtual Usuario UsuarioFechamento { get; set; }

But still the same error persists.

  • One thing I know is already incorrect. The annotation ForeignKey must be on the property that represents the object, in this case, Usersopening and Usersclosing. And it should also point to the field in the bank that will be the foreign key, in this case, Usersopenturaid and Userslock. If you keep having trouble is because there are more mistakes, you post that we try to help.

  • So, but according to the documentation the annotation can be done in reverse. have an example showing: http://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-first.aspx

  • I got it, I didn’t really know it that way. I always did it that way. So it must be something else.

1 answer

1


 [ForeignKey("UsuarioAbertura")]
 public long UsuarioAberturaId { get; set; }
 public virtual Usuario UsuarioAbertura { get; set; }

Here you tried to map a ratio from 1 to 1? If you tried this incorrect, this is a fraction of the setting that makes the ratio 1 to N, and this is enough for the Entity to understand this relationship when creating/editing the database.

Recommend: http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

The problem is that the cascade exclusion is active. When you have Manifestation delete, it will leave deleting all related Contents and the same will leave deleting all linked User, however I have 2 relationships for User, where both sides of the relationship can come out knocking down the same tables and there will be this conflict that the Entity Framework accused.

Manifestacao 
-->> DROP CASCADE Conteudo
     -->> DROP CASCADE Usuario (possui dois relacionamento "iguais" a sofrer exclusão)
          -->> UsuarioAbertura
          -->> UsuarioFechamento 

The solution is to fix this relationship if the intention is 1 to 1 and if it is 1 to N you will have to use the Fluent API to configure that it is not a cascade delete or use the following line to delete the DELETE CASCADE convention on OnModelCreating():

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
  • Thank you, Gabriel!

Browser other questions tagged

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