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

时间:2011-07-26 00:19:19

标签: c# .net entity-framework exception-handling 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; }
}

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

因此,当我创建新的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
            }

        }

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

但是,当我尝试使用以下代码保存时,我收到违反PRIMARY KEY约束错误

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

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

2 个答案:

答案 0 :(得分: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();
}

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

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

答案 1 :(得分:0)

您如何创建新标签?如何将现有或创建的实体附加到文章中。

使用类似

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

阅读这篇文章http://thedatafarm.com/blog/data-access/inserting-many-to-many-relationships-in-ef-with-or-without-a-join-entity/