Код элемента Entity Framework Сначала: добавление ко многим отношениям по ID

У меня есть отношение "Много-ко-многим", определенное следующим образом:

public class Post
{
   //NOT SHOWN: Other properties
   public virtual ICollection<Tag> Tags { get; set; }
}

Все примеры, которые я вижу, добавят к отношениям "многие ко многим":

//Get the tag with ID of 1
var tag = context.Tags.Find(1);
// associate tag with ID of 1 with myPost
myPost.Tags.Add(tag);

Но это кажется утомительным/неэффективным, если я просто знаю идентификатор тега (ов), который я хотел бы связать с моим сообщением.

В идеале я просто хотел бы открыть List<int> TagIds на моей почтовой сущности и иметь возможность добавлять теги, добавив теги идентификаторов в список, но мне не удалось определить, возможно ли это с использованием EF Code First.

Итог: какой лучший способ добавить элементы ко многим отношениям, учитывая, что у меня есть только те объекты, которые я хочу связать. (например, если у меня есть список идентификаторов тегов, какой лучший способ связать эти теги с сообщением?)

Ответ 1

Используйте такой код:

// Existing post without loading it from the database
var myPost = new Post() { Id = ... };
context.Posts.Attach(post);

// For each id of existing tag 
foreach (int tagId in someExistingTagIds)
{
    var tag = new Tag() { Id = tagId };
    context.Tags.Attach(tag);

    // Make a new relation
    post.Tags.Add(tag);
}

context.SaveChanges();

Это позволит вам создать отношение MN к существующим объектам, не загружая ничего из базы данных. Вам просто нужно знать идентификаторы существующих объектов.

Ответ 2

Надеюсь, кто-то с большим опытом работы в EF сможет вам помочь, но если бы я был в этой ситуации, я бы сам моделировал отношения MM (так, моделируя таблицу ссылок). Таким образом, вы можете

myPost.PostTags.Add(new PostTagLink(){
  TagID = 1
});

Но тогда вам придется иметь дело с дополнительным объектом таблицы ссылок. На обратной стороне, если вы собираетесь добавить дополнительные свойства в отношения, вам все равно придется это делать.

Если есть лучший способ обойти это, я тоже хотел бы знать.

Ответ 3

Почему вы говорите, что это неэффективно. Если вы объявите его Виртуальным, он не будет загружен до тех пор, пока вы не получите доступ к нему при включении ленивой загрузки. Скажем, если у вас есть список значений Id. Затем, когда вы хотите загрузить весь список, вам нужно вызвать getById для всех значений. Это очень неэффективно, чем использование ленивой загрузки.