Как избежать избыточности / сохранения данных в отношениях EF Core «многие ко многим»? - PullRequest
0 голосов
/ 20 октября 2019

Может кто-нибудь ответить мне, как правильно добавлять и вставлять данные в таблицу соединений / отношения многие ко многим с Entity Framework Core, без многократного сохранения данных?

Мой контекст базы данных выглядит следующим образом:Свободный API:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>().HasIndex(u => u.Username).IsUnique(true);

     builder.Entity<GroupMembers>().HasKey(gm => new { gm.UserId, gm.GroupId });
     builder.Entity<GroupMembers>().HasOne(gm => gm.Group).WithMany(group.GroupMembers).HasForeignKey(gm => gm.GroupId);
     builder.Entity<GroupMembers>().HasOne(gm => gm.User).WithMany(user.GroupMembers).HasForeignKey(gm => gm.UserId);
}

Вот мои модели для пользователя, группы и таблицы соединений между ними:

public class User
{
    [Key]
    public Guid Id { get; set; }
    public string Username { get; set; }
    public List<GroupMembers> GroupMembers { get; set; } = new List<GroupMembers>();
}
public class Group
{
    [Key]
    public Guid Id { get; set; }
    public string GroupName { get; set; }
    public List<GroupMembers> GroupMembers { get; set; } = new List<GroupMembers>();
}
public class GroupMembers
{
    [Key]
    public Guid UserId { get; set; }
    public User User { get; set; }

    [Key]
    public Guid GroupId { get; set; }
    public Group Group { get; set; }
}

Теперь вопрос в том;Как мне добавить отношения между ними / вставить в таблицу GroupMembers? Это так?

public class DatabaseHelper : IDatabaseHelper
{
    private readonly AppDatabaseContext _databaseContext;

    private readonly AppDatabaseContext _databaseContext;

    GroupMembers groupMember = new GroupMembers
    {
        Group = group,
        GroupId = group.Id,
        User = user,
        UserId = user.Id
    };

    User user = ...
    Group group = ...

    user.GroupMembers.Add(groupMember);
    group.GroupMembers.Add(groupMember);

    _databaseContext.Users.Update(user);
    _databaseContext.Groups.Update(group);
    _databaseContext.SaveChanges();
}

Если это правильное решение, то не правда ли, что данные для членов группы будут сохранены два раза, например. избыточность? Группа имеет информацию о своих членах, а Пользователь имеет информацию о членстве в группе. При обычной RDBS информация о членстве сохраняется в таблицах объединения, а именно GroupMembership только один раз, без какой-либо избыточности. Как мне сделать это с EF Core многие-ко-многим?

EDIT Должен ли GroupMembers быть DbSet <> или только пользователь и группа должны быть DbSet <>?

public class AppDatabaseContext : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Group> Groups { get; set; }
        //public DbSet<GroupMembers> GroupMembers{ get; set; }
    }
    ...
}

Ответы [ 3 ]

1 голос
/ 20 октября 2019

Это так?

Возможно, но метод с наименьшими издержками всегда должен иметь DbSet<GroupMember>. (Совет: не используйте множественные имена классов). Тогда все, что вам нужно, это два значения идентификатора:

var groupMember = new GroupMember
{
    GroupId = groupId,
    UserId = userId
};

_databaseContext.GroupMembers.Add(groupMember);
_databaseContext.SaveChanges();

Это может быть встроено в любом случае использования. Возможны случаи, когда из пользовательского интерфейса или API предоставляются только значения идентификаторов, или User или Group - это отправная точка, предоставляющая одно значение идентификатора и значения идентификаторов другой части. Все сводится к этому маленькому куску кода.

0 голосов
/ 20 октября 2019

не правда ли, что данные для членов группы будут сохранены два раза, например. избыточность?

Нет. Вы правильно установили ключ на GroupMember, чтобы предотвратить это:

builder.Entity<GroupMembers>().HasKey(gm => new { gm.UserId, gm.GroupId });
0 голосов
/ 20 октября 2019

Я думаю, что efcore tracker заботится о ситуации и не вставляет запись дважды. Если это не так, вы можете вставить свой объект groupmember в базу данных, а не обновлять как группы, так и пользователей. Что также лучше с точки зрения производительности, поскольку требует только одного запроса.

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