Использование соединительной таблицы в отношениях многих ко многим - PullRequest
0 голосов
/ 27 ноября 2018

Я изучаю EF Core.Скажем, у меня есть связь «многие ко многим» с такой соединительной таблицей:

public class PostTag
{
    public int PostId { get; set; }
    public Post Post { get; set; }

    public int TagId { get; set; }
    public Tag Tag { get; set; }
}

Скажем, я хотел выполнить вставку в базу данных.

var post = new Post { Id=Guid.NewGuid(), Description="Test Post" };
var tag = new Tag { Id=Guid.NewGuid(), Description="Test Text"  };
var PostTag = new PostTag { Post=post; Tag=tag; PostId=Post.Id, TagId=Tag.Id};
context.Add(PostTag);

Эта одна вставка выглядит так:

1) Insert a post.
2) Insert a Tag
3) Insert a PostTag

Q1) Почему PostTag содержит PostId и TagId?Эта информация содержится в Post и Tag (также два поля в PostTag).Похоже, что эти поля дублируются.

Q2) Добавляет ли PostTag также сообщение и тег?

1 Ответ

0 голосов
/ 28 ноября 2018

Почему PostTag содержит PostId и TagId?Эта информация содержится в Post и Tag (также два поля в PostTag).Похоже, что эти поля дублируются.

Как вы знаете, PostTag.PostId является внешним ключом, который ссылается на Post.Id, а PostTag.TagId является внешним ключом, который ссылается на Tag.Id.PostTag.PostId называется Foreign Key Property, а PostTag.Post - это Navigation Property.

На самом деле, если у вас нет свойства внешнего ключа для свойства навигации в явном виде, EF Core также будет работать должным образом.В этом случае два свойства теневого внешнего ключа PostId и TagId будут введены для вас автоматически.Он называется Shadow Properties.

Свойства теней могут быть созданы по соглашению, когда обнаружена связь, но в классе зависимого объекта не найдено свойство внешнего ключа.В этом случае будет введено свойство внешнего ключа.Свойство теневого внешнего ключа будет иметь имя <navigation property name><principal key property name> (для именования используется навигация по зависимому объекту, которая указывает на главный объект).Если имя свойства основного ключа включает в себя имя свойства навигации, тогда оно будет просто <principal key property name>.Если у зависимого объекта нет свойства навигации, то вместо него используется имя основного типа.

  1. Хотя этот внешний ключ может быть выведен с помощью PostTag.Post.Id и PostTag.Tag.Id соответственно, они не дублируются .

    Допустим, у нас есть существующая база данных, в которой внешние ключи названы fk_post_id и fk_tag_id, и вы хотите переименовать свойство внешнего ключа PostId в MyPostId, мы не можем опустить *Свойства 1045 * и TagId:

    public class PostTag
    {
        [Column("fk_post_id")]
        public Guid MyPostId { get; set; }
        [ForeignKey("MyPostId")]
        public Post Post { get; set; }
    
    
        [Column("fk_tag_id")]
        public Guid TagId { get; set; }
        public Tag Tag { get; set; }
    }
    
  2. Рекомендуется иметь свойство внешнего ключа, определенное в классе зависимого объекта для свойства навигации

Добавляет ли PostTag также сообщение и тег?

Ваш код автоматически добавляет сообщение и тег для вас, поскольку он знает, что вам нужносоздать новый пост и новый тег.Но это не всегда так.Это зависит от состояния отслеживания и самого объекта.

Если вы выполните следующий код:

    var tagTracked = this._dbContext.Tag.FirstOrDefault();
    var post = new Post { Id=Guid.NewGuid(), Description="Test Post3" };
    var PostTag = new PostTag { 
        Post=post, 
        Tag=tagTracked, 
        MyPostId= post.Id, 
        TagId= tagTracked.Id,
    };
    this._dbContext.Add(PostTag);
    this._dbContext.SaveChanges();

tagTracked вставляться не будет.Если вы хотите вставить новую запись тега, вам нужно сделать tag неотслеживаемым:

    var tagTracked = this._dbContext.Tag.AsNoTracking().FirstOrDefault();
    tagTracked.Id = Guid.NewGuid();
    var post = new Post { Id=Guid.NewGuid(), Description="Test Post3" };
    var PostTag = new PostTag { 
        Post=post, 
        Tag=tagTracked, 
        MyPostId= post.Id, 
        TagId= tagTracked.Id,
    };
    this._dbContext.Add(PostTag);
    this._dbContext.SaveChanges();

Опять же, он вставит новую запись тега в базу данных.Для получения дополнительной информации см. документы здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...