Добавление элемента с отношением "многие ко многим" в Entity Framework
Я получаю ошибку нарушения первичного ключа, когда пытаюсь добавить элемент с отношением "многие ко многим":
у меня есть два класса - статьи и теги, которые имеют многие-ко-многим отношения :
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; }
}
когда я добавляю новую статью, я разрешаю пользователю вводить любые теги, а затем я хочу создать новый тег, если тег еще не создан в базе данных или добавить тег в коллекцию тегов объекта статьи, если тег уже существует.
поэтому, когда я создаю новый объект статьи, я вызываю следующую функцию:
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
}
}
эта функция в основном проверяет, есть ли доступный тег в базе данных, и если да, то возвращает этот тег, который затем добавляется в коллекцию тегов объекта Article с помощью article.Метить.Добавлять.)(
однако, когда я пытаюсь сохранить это, используя приведенный ниже код, я получаю нарушение ошибки ограничения первичного ключа
db.Entry(article).State = EntityState.Modified;
db.SaveChanges();
Я не могу понять, как я следует просто создать связь между статьей и уже существующим тегом.
2 ответов
используйте один и тот же экземпляр контекста для всей обработки вашей операции, и ваша жизнь будет намного проще:
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();
}
Как вы создаете новые теги? И как вы присоединяете существующий или созданный объект к статье.
использовать что-то вроде
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/