Entity framework Many-to-Many Ientitychangetracker error. How to resolve?

Asked

Viewed 271 times

2

I have a Many-to-Many relationship and my tables are correct about the relationship in the database. The problem is that my insertion works perfectly when you don’t use an existing entity in the database, but when I search the database and add again it understands that I’m not just "referencing" but adding a new entity.

news entity:

[Table("Noticia")]
public class
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string Titulo { get; set; }

    #region Relationships
    public virtual ICollection<Tag> Tags { get; set; }
    #endregion Relationships
}

Tag model:

[Table("Tag")]
public class Tag
{
    [Key]
    [Required]
    [MinLength(3), MaxLength(30)]
    public string Descricao { get; set; }

    #region Relationships
    [Required]
    public virtual ICollection<Noticia> Noticias { get; set; }        
    #endregion Relationships
}

this relationship (Icollection

Controller:

[HttpPost, ValidateAntiForgeryToken]
    public ActionResult Create(NoticiaViewModel vModel)
    {
         if (vModel != null && vModel.ArquivoImagem != null && vModel.ArquivoImagem.ContentLength > 0)
         {
              vModel.Id = Guid.NewGuid();
              vModel.DataPostagem = DateTime.Now;
              vModel.Tags = ObterTags(vModel.TagsEmLinha, vModel.Id);
              vModel.UsuarioId = User.ToAvatarPrincipal().AvatarIdentity.Id;
              vModel.Imagem = new Imagem
              {
                  Id = Guid.NewGuid(),
                  CaminhoImagem = FileUploaderHelper.Upload(vModel.ArquivoImagem, User.ToAvatarPrincipal().AvatarIdentity.TipoUsuario,vModel.Id.ToString())
              };

              if (ModelState.IsValid)
              {
                  ///TODO: Quando a tag já foi utilizada, esta dando erro de primary key já existente na Tag.
                  if (_noticiaService.Gravar(ModelBuilderHelper.BuildNoticia(vModel)))
                  return RedirectToAction("List");
              }
        }
                return View(vModel);
   }

   private List<Tag> ObterTags(string tagsEmLinha)
   {
        if (!string.IsNullOrEmpty(tagsEmLinha))
        {
             Tag tagFromDb = null;
             var tags = new List<Tag>();
             if (tagsEmLinha.Contains(","))
             {
                  foreach (var tagDescricao in tagsEmLinha.Split(','))
                  {
                       tagFromDb = DefineTag(tags, tagDescricao);
                  }
             }
             else
             {
                  tagFromDb = DefineTag(tags, tagsEmLinha);
             }
             return tags;
        }
        return null;
   }

   private Tag DefineTag(List<Tag> tags, string tagDescricao)
   {
        Tag tagFromDb = _tagService.ObterPor(tagDescricao);
        if (tagFromDb != null)
            tags.Add(tagFromDb);
        else
        {
            tags.Add(new Tag
            {
                 Descricao = tagDescricao
            });
        }

        return tagFromDb;
   }

Remembering that, adding a nonexistent news with a nonexistent tag, it inserts all tables correctly (inserts in news, tag and tagNoticia). But if I insert a news for a tag that already exists (do the Many-to-Many relation), the error occurs:

Error:

An Entity Object cannot be referenced by Multiple instances of Ientitychangetracker.

1 answer

1

I changed my service to the following:

public bool GravarNoticia(Noticia noticia, List<string> tags)
{
    Noticia novaNoticia = null;

    using (_noticiaRepository)
    {
        try
        {
            novaNoticia = new Noticia
            {
                DataPostagem = noticia.DataPostagem,
                Descricao = noticia.Descricao,
                Id = noticia.Id,
                Imagem = noticia.Imagem,
                Titulo = noticia.Titulo,
                UsuarioId = noticia.UsuarioId,
                Tags = new List<Tag>()
            };

            foreach (var tag in tags)
            {
                var tagFromDb = _noticiaRepository.ObterTag(tag);

                if (tagFromDb != null)
                    novaNoticia.Tags.Add(tagFromDb);
                else
                    novaNoticia.Tags.Add(new Tag
                    {
                        Descricao = tag,
                        Id = Guid.NewGuid()
                    });
            }

            return Gravar(novaNoticia);
        }
        catch (System.Exception)
        {
            throw;
        }
    }
}

What happened was that I used two different instances of my context, one in the search and the other in the insertion, that’s where the conflict happened, because the Entity Framework did not understand that it was the same entity and tried to insert again over an already nonexistent.

official link from where I based to get the answer: https://lostechies.com/derekgreer/2015/11/01/survey-of-entity-framework-unit-of-work-patterns/

Browser other questions tagged

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