Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

c# - Adding Item with Many-to-Many Relationship In Entity Framework

I am getting a primary key violation error when I attempt to add an item with a many-to-many relationship:

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

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; }
}

When I add a new Article I allow the user to input any Tags and then I want to create a new Tag if the Tag isn't created yet in the database or add the Tag to the Tags collection of the Article object if the Tag already exists.

Therefore when I am creating the new Article object I call the below function:

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 function basically checks if there is an available Tag in the database and if so returns that Tag which is then added to the Tag collection of the Article object using article.Tags.Add().

However, when I attempt to save this using the below code I get a Violation of PRIMARY KEY constraint error

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

I can't figure out how I should go about just creating a relationship between the Article and the already existing Tag.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use the same context instance for the whole processing of your operation and your life will be much easier:

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 don't want to load the article from database (that query is redundant if you know that article exists) you can 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();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...