Entity Framework Add Item with Many-to-Many Relationship

.net c# entity-framework exception primary-key

Question

When I try to add an item with a many-to-many connection, I receive a primary key violation error:

I have two classes with a many-to-many relationship: Articles and Tags.

public class Article
{
    public int ID { get; set; }
    public string Text { get; set; }
    public   ICollection<Tag>  Tags { get; set; }
}

public class Tag
{ 
    [Key]
    public string UrlSlug { get; set; }
    public string Name { get; set; }
    public ICollection<Article> Articles{ get; set; }
}

Allowing the user to enter any Tags when adding a new Article allows me to decide whether to generate a new Tag in the database or add an existing Tag to the Tags collection of the Article object.

Consequently, I call the following code when I create the new Article object:

public static Tag GetOrLoadTag(String tagStr)
{
    string tagUrl = Tag.CreateTagUrl(tagStr);
    var db = new SnippetContext();
    var tagFromDb = from tagdummy in db.Tags.Include(x => x.Articles)
                    where tagdummy.UrlSlug == tagUrl
                    select tagdummy;
    if (tagFromDb.FirstOrDefault() != null)
    { return tagFromDb.FirstOrDefault(); }
    else
    {
        //create and send back a new Tag
    }
}

This method simply determines if a Tag is accessible in the database and, if it is, returns it. The returned Tag is then added to the Article object's Tag collection using article. Tags.Add().

However, I see a violation of the PRIMARY KEY constraint error when I try to save this using the code below.

 db.Entry(article).State = EntityState.Modified;
 db.SaveChanges();

I'm having trouble figuring out how to just establish a connection between the Article and the current Tag.

1
9
7/15/2019 9:09:26 PM

Accepted Answer

Your life will be lot simpler if you use the same context instance throughout the execution of your operation:

using (var ctx = new MyContext())
{
    Article article = ctx.Articles.Single(a => a.Id == articleId);
    Tag tag = ctx.Tags.SingleOrDefault(t => t.UrlSlug == tagUrl);
    if (tag == null) 
    {
       tag = new Tag() { ... }
       ctx.Tags.AddObject(tag);
    }

    article.Tags.Add(tag);
    ctx.SaveChanges();
}

If you know the item already exists and you don't want to load it from the database, you may use:

using (var ctx = new MyContext())
{
    Article article = new Article() { Id = articleId };
    ctx.Articles.Attach(article);

    Tag tag = ctx.Tags.SingleOrDefalut(t => t.UrlSlug == tagUrl);
    if (tag == null) 
    {
       tag = new Tag() { ... }
       ctx.Tags.AddObject(tag);
    }

    article.Tags.Add(tag);
    ctx.SaveChanges();
}
17
6/24/2017 1:01:04 PM

Popular Answer

What steps are involved in adding new tags? And how do you connect the newly generated or existing object to the article.

Use a device like

Article a = new Article(...);
a.tags.add(GetOrLoadTag("some tag"));

Click here to read this article.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow