Как заставить отношения «один ко многим» между 3 объектами работать с Entity Framework Core 2.1 - сначала код - PullRequest
0 голосов
/ 06 июня 2019

У меня есть 3 сущности, сопоставленные друг с другом с отношением один ко многим, один из них должен быть сопоставлен с обоими, что приводит к нежелательным отношениям многие ко многим.Вот логика, лежащая в основе отображения:

  • Пользователь может иметь много сообщений;Пост имеет только одного пользователя.
  • Пользователь может иметь много категорий;Категория имеет только одного пользователя.
  • Категория может иметь много сообщений;Пост имеет только одну категорию.

Вот мой код: Пользователь

Table("Users")]
Public Class User
{
        [Key]
        public int UserId { get; set; }
        [Required]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        [Required]
        public string UserName { get; set; }
        public DateTime CreatedAt { get; set; }

        public ICollection<Posts> Posts { get; set; }
        public ICollection<Category> Categories { get; set; }
}

Пост

[Table("Posts")]
    public class Post
    {
        [Key]
        public int PostId { get; set; }
        [Required]
        public string Title { get; set; }
        [Required]
        public string Description { get; set; }
        [Required]
        public string Text { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime? UpdatedAt { get; set; }

        public int UserId { get; set; }
        public User User { get; set; }

        public int CategoryId { get; set; }
        public Category Category { get; set; }

    }

Категория

 [Table("Categories")]
    public class Category
    {
        [Key]
        public int CategoryId { get; set; }
        [Required]
        public string Name { get; set; }
        [Required]
        public string Description { get; set; }
        public DateTime CreatedAt { get; set; }

        public int UserId { get; set; }
        public User User { get; set; }

        public ICollection<Post> Posts { get; set; }
    }

Мой Db Context

 public class BlogContext : DbContext
    {

        public DbSet<User> Users { get; set; }
        public DbSet<Post> Posts{ get; set; }
        public DbSet<Category> Categories { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<User>(entity =>
            {
                entity.HasMany<Post>(s => s.Posts)
                .WithOne(u => u.User)
                .HasForeignKey(s => s.UserId)
                .OnDelete(DeleteBehavior.Restrict);

                entity.HasMany<Category>(c => c.Categories)
                .WithOne(u => u.User)
                .HasForeignKey(c => c.UserId)
                .OnDelete(DeleteBehavior.Restrict);

                entity.Property(u => u.CreatedAt)
                .HasDefaultValueSql("SYSUTCDATETIME()");
            });

            modelBuilder.Entity<Post>(entity =>
            {

                entity.HasOne<Category>(s => s.Category)
                .WithMany(c => c.Posts)
                .HasForeignKey(s => s.PostId);

                entity.HasOne<User>(s => s.User)
                .WithMany(u => u.Posts)
                .HasForeignKey(s => s.PostId);

                entity.Property(s => s.CreatedAt)
                .HasDefaultValueSql("SYSUTCDATETIME()");
            });


            modelBuilder.Entity<Category>(entity =>
            {
                entity.HasMany<Post>(c => c.Posts)
                .WithOne(s => s.Category)
                .HasForeignKey(c => c.PostId)
                .OnDelete(DeleteBehavior.Restrict);


                entity.Property(c => c.CreatedAt)
                .HasDefaultValueSql("SYSUTCDATETIME()");
            });

        }
    }

Я столкнулся с этой проблемой при вставке сообщений:

The property 'PostId' on entity type 'Post' has a temporary value

Я понял, что я вызвал отношения многие ко многим с тем, как я реализовал DbContext,Как я могу это исправить?Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 07 июня 2019

Вы неправильно настроили внешний ключ.Давайте рассмотрим ваш код Entity<Post>(entity=>{ /* ... */ }):

modelBuilder.Entity<Post>(entity =>
{
    entity.HasOne<Category>(s => s.Category)
        .WithMany(c => c.Posts)
        <b>.HasForeignKey(s => s.PostId);</b>  // line A: it is not correct!

    entity.HasOne<User>(s => s.User)
        .WithMany(u => u.Posts)
        <b>.HasForeignKey(s => s.PostId);</b> // line B: it is not correct!

    entity.Property(s => s.CreatedAt)
        .HasDefaultValueSql("SYSUTCDATETIME()");
});

Обратите внимание, что строка A и строка B неверны.Как и в обоих случаях, зависимым объектом является Post.Ваш код приведет к внешнему ключу, как показано ниже:

CREATE TABLE [Posts] (
    [PostId] int NOT NULL,
    [Title] nvarchar(max) NOT NULL,
    [Description] nvarchar(max) NOT NULL,
    [Text] nvarchar(max) NOT NULL,
    [CreatedAt] datetime2 NOT NULL DEFAULT (SYSUTCDATETIME()),
    [UpdatedAt] datetime2 NULL,
    [UserId] int NOT NULL,
    [CategoryId] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([PostId]),
    CONSTRAINT [FK_Posts_Categories_PostId] FOREIGN KEY ([PostId]) REFERENCES [Categories] ([CategoryId]) ON DELETE NO ACTION,
    CONSTRAINT [FK_Posts_Users_PostId] FOREIGN KEY ([PostId]) REFERENCES [Users] ([UserId]) ON DELETE NO ACTION
);

Поэтому вам нужно изменить свой код, как показано ниже:

modelBuilder.Entity<Post>(entity =>
{
    entity.HasOne<Category>(s => s.Category)
        .WithMany(c => c.Posts)
        //.HasForeignKey(s => s.PostId);
        .HasForeignKey(s => s.CategoryId);

    entity.HasOne<User>(s => s.User)
        .WithMany(u => u.Posts)
        //.HasForeignKey(s => s.PostId);
        .HasForeignKey(s => s.UserId);

    entity.Property(s => s.CreatedAt)
        .HasDefaultValueSql("SYSUTCDATETIME()");
});

По той же причине, вы также должны изменить частьEntity<Category>(entity=>{ /* ... */ }) как показано ниже:

modelBuilder.Entity<Category>(entity =>
{
    entity.HasMany<Post>(c => c.Posts)
        .WithOne(s => s.Category)
        //.HasForeignKey(c => c.PostId)     // remove this line
        .HasForeignKey(c => c.CategoryId)   // add this line
        .OnDelete(DeleteBehavior.Restrict);


    entity.Property(c => c.CreatedAt)
        .HasDefaultValueSql("SYSUTCDATETIME()");
});
0 голосов
/ 07 июня 2019

Вы ошиблись в

    modelBuilder.Entity<Post>(entity =>
        {

            entity.HasOne<Category>(s => s.Category)
            .WithMany(c => c.Posts)
            .HasForeignKey(s => s.PostId);

            entity.HasOne<User>(s => s.User)
            .WithMany(u => u.Posts)
            .HasForeignKey(s => s.PostId);

            entity.Property(s => s.CreatedAt)
            .HasDefaultValueSql("SYSUTCDATETIME()");
        });

Модель категории таблицы не имеет PostId, а модель пользователя не имеет. Исправьте это.

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