Проблема отношений между моделями сущностей - PullRequest
0 голосов
/ 11 февраля 2019

Я хочу создать систему «Мне нравится и не нравится» в моем проекте, у меня есть модель для Пользователя, модель для Сообщения, модель для Комментария со следующими отношениями:

Пользователь 1 ---> * Сообщение

Пользователь 1 ---> * Комментарий

Публикация 1 ---> * Комментарий

Теперь я хочу добавить новую модель под названием Like с отношениями ниже:

Post 1 ---> * Like User 1 ---> * Like

, но когда я хочу обновить базу данных, я получаю сообщение об ошибке: «может вызвать циклы или несколько каскадных путей» Iобнаружил, что если я удаляю одно из своих свойств, оно исправляет ошибку, например:

public class Post
{

    public Post()
    {

    }

    [Key]
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<Like> Likes { get; set; }

    public virtual List<Comment> Comments { get; set; }

}



public class Like
{

    public Like()
    {

    }

    [Key]
    public int Id { get; set; }

    public bool IsLike { get; set; }


    public int postId { get; set; } // I remove these properties

    public virtual Post post { get; set; }


    public int commentId { get; set; }  // I remove these properties

    public virtual Comment comment { get; set; }

}

для исправления ошибки «нескольких каскадов» удаляю свойства «PostId» и «commentId».

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

может любойтело скажите мне проблему?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Проблема в том, что ваша база данных не достаточно нормализована.

Я вижу, что пользователи могут создавать Posts.Они также могут Comment на Post и Like комментариев.

Поскольку Comment является Comment about a Post, Like для этого Comment автоматически становится Like на Post, о котором говорится в комментарии

Другими словами: если кто-то создал комментарий (4) к Посту (10), то смешно создавать лайк для комментария (4) и Поста(20).комментарий (4) не имеет никакого отношения к записи (20)!

Каждый лайк создается ровно одним пользователем с одним комментарием.Пользователь создает ноль или более лайков (один ко многим), а комментарий был добавлен ноль или больше раз (также один ко многим)

Итак, у вас есть следующая последовательность действий:

  • Пользователь 1 создает сообщение 10: Сообщение 10 имеет внешний ключ CreateByUserId 1
  • Пользователь 2 создает комментарий 20 к сообщению 10. Комментарий 20 имеет CommentedByUserId 2 и PostId 20
  • Пользователь 3лайки комментирует 20. Лайк 30 имеет LikedByUserId 3 и CommentId 20

Это достаточно нормализовано для структуры сущностей.Чтобы сделать отношения более понятными, я немного изменил внешние ключи.

class User
{
     public int Id {get; set;}
     ...

     // Every User creates zero or more Posts (one-to-many)
     public virtual ICollection<Post> Posts {get; set;}

     // Every User creates zero or more Comments (one-to-many)
     public virtual ICollection<Comment> Comments {get; set;}

     // Every User creates zero or more Likes (one-to-many)
     public virtual ICollection<Like> Likes {get; set;}
}

class Post
{
    public int Id {get; set;}
    ...

    // Every Post is posted by exactly one User, using foreign key
    public int PostedByUserId {get; set;}
    public User User {get; set;}

    // Every Post has zero or more Comments (one-to-many)
    public virtual ICollection<Comment> Comments {get; set;}
}

И комментарий к классам и т.п.:

class Comment
{
    public int Id {get; set;}
    ...

    // Every Comment is posted by exactly one User, using foreign key
    public int CommentedByUserId {get; set;}
    public virtual User User {get; set;}

    // Every Comment is about exactly one Post, using foreign key
    public int PostId {get; set;}
    public virtual Post Post {get; set;}

    // Every Comment has zero or more Likes (one-to-many)
    public virtual ICollection<Like> Likes {get; set;}
}
class Like
{
    public int Id {get; set;}
    ...

    // Every Like is created by exactly one User, using foreign key
    public int LikedByUserId {get; set;}
    public virtual User User {get; set;}

    // Every Like is about exactly one Comment, using foreign key
    public int CommentId {get; set;}
    public virtual Comment Comment {get; set;}
}

Поскольку мои внешние ключи отличаются от условных обозначений, я должен сообщить об этом сущностирамки об этих внешних ключах, используя свободный API:

Сообщение имеет внешний ключ для пользователя:

modelBuilder.Entity<Post>()
    .HasRequired(post => post.User)
    .WithMany(user => user.Posts)
    .HasForeignKey(post => post.CreatedByUserId);

Комментарий имеет внешние ключи для пользователя и сообщения:

var commentEntity = modelBuilder.Entity<Comment>();
commentEntity.HasRequired(comment => comment.User)
    .WithMany(user => user.Comments)
    .HasForeignKey(comment => comment.CommentedByUserId);
commentEntity.HasRequired(comment => comment.Post)
    .WithMany(post => post.Comments)
    .HasForeignKey(comment => comment.PostId);

Нравитсяимеет внешние ключи для пользователя и комментария:

var likeEntity = modelBuilder.Entity<Like>();
likeEntity.HasRequired(like => like.User)
    .WithMany(user => user.Likes)
    .HasForeignKey(like => like.LikedByUserId);
likeEntity.HasRequired(like  => like.Comment)
    .WithMany(comment => comment.Likes)
    .HasForeignKey(like => like.CommentId);

Если в будущем вы захотите предоставить пользователям возможность ставить лайк вместо комментария или, возможно, как пользователь, отношения будут очень похожи,Начните с предоставления пользователю правильного virtual ICollection<...> (каждому пользователю нравится ноль или более ...), и вы автоматически узнаете, куда ставить внешние ключи

0 голосов
/ 11 февраля 2019

Для лучшего дизайна разделите таблицу «Мне нравится» для Post и Comment следующим образом:

public class User
{
    [Key]
    public int Id { get; set; }

    //......

    public virtual List<Post> Posts { get; set; }

    public virtual List<Comment> Comments { get; set; }

    public virtual List<PostLikes> PostLikes { get; set; }

    public virtual List<CommentLIkes> CommentLikes { get; set; }
}


public class Post
{
    [Key]
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<PostLike> PostLikes { get; set; }

    public virtual List<Comment> Comments { get; set; }
}

public class Comment
{
    [Key]
    public int Id { get; set; }

    public string CommentBody { get; set; }

    //.....

    public virtual List<CommentLike> CommentLikes { get; set; }
}

public class PostLike
{
    [Key]
    public int Id { get; set; }

    public int PostId { get; set; }

    public int UserId {get; set;}

    public bool IsLike { get; set; }

    public virtual Post post { get; set; }
    public virtual User User { get; set; }
}

public class CommentLike
{
    [Key]
    public int Id { get; set; }

    public int CommentId { get; set; }

    public int UserId {get; set;}

    public bool IsLike { get; set; }

    public virtual Comment Comment { get; set; }
    public virtual User User { get; set; }

}

Теперь создайте новую миграцию и обновите базу данных соответствующим образом.

Примечание: вы можете столкнуться с проблемой каскадного удаления при обновлении миграции.Если вы сталкиваетесь, дайте мне знать, я обновлю ответ с помощью конфигурации Fluent API.

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