在实体框架中添加具有多对多关系的项目

Jud*_*udo 9 .net c# entity-framework exception primary-key

当我尝试添加具有多对多关系的项时,我收到主键冲突错误:

我有两个类 - 文章和标签有多对多的关系:

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; }
}
Run Code Online (Sandbox Code Playgroud)

当我添加新文章时,我允许用户输入任何标签,然后我想创建一个新标签,如果尚未在数据库中创建标签,或者如果标签已经将标签添加到文章对象的标签集合中存在.

因此,当我创建新的Article对象时,我调用以下函数:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

此函数基本上检查数据库中是否有可用的Tag,如果是,则返回该Tag,然后使用article.Tags.Add()将其添加到Article对象的Tag集合中.

但是,当我尝试使用下面的代码保存它时,我得到一个违反PRIMARY KEY约束错误

 db.Entry(article).State = EntityState.Modified;
 db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚我应该如何在文章和现有标签之间建立关系.

Lad*_*nka 17

使用相同的上下文实例进行整个操作处理,您的生活将更加轻松:

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();
}
Run Code Online (Sandbox Code Playgroud)

如果您不想从数据库加载文章(如果您知道该文章存在,该查询是多余的)您可以使用:

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();
}
Run Code Online (Sandbox Code Playgroud)