【问题标题】:Can I assign many-to-many relations with ID only?我可以仅使用 ID 分配多对多关系吗?
【发布时间】:2018-03-01 15:09:09
【问题描述】:

我正在使用 asp.net mvc 核心和实体框架构建一个 web api。

我有两个对象,它们之间存在多对多关系。

class User
{
    public string ID { get; set; }
    public List<Message> Inbox { get; set; }
}

class Message
{
    public int ID { get; set; }
    public List<User> Recipients { get; set; }
}

为了创建一条新消息,客户端向我的控制器发送一个 JSON,其结构如下:

// POST /api/message
{
    body: "...", // the body and other properties of the message
    recipients: ["user1", "user2"] // a list of the IDs of the recipients of this message
}

所以基本上我需要创建一个新的Message 对象并根据我在 JSON 中收到的用户 ID 分配它的 Recipients 属性。

到目前为止,我正在从数据库中提取每个 User 对象以将其分配给我的 Message,但这看起来很浪费资源。

foreach (var userId in json.recipients)
{
    var userObject = _dbContext.Users.Find(userId);
    message.Recipients.Add(userObject)
}

一定有更好的方法,对吧?如何在不从数据库中提取所有内容的情况下分配收件人?或者至少只做一个请求?

【问题讨论】:

  • 首先,尝试var userRecipients = _dbContext.Users.Where(user =&gt; json.recipients.Contains(user.ID)).ToList();。那么你应该可以使用AddRange()
  • 这种关系不是多对多吗?一条消息可以有多个收件人,一个收件人(用户)可以有多个消息。
  • 无论如何,你可以这样做:message.Recipients = json.recipients.Select(u => new User { Id = u}).ToList()。用户必须已经在数据库上。我有一个可行的解决方案,但对于多对多关系,我认为这是适合您情况的模型。如果您希望我发布作为答案,请告诉我
  • @jpgrassi 哦……你说得对!感谢您指出了这一点!我编辑了问题以反映变化。我很想看看你的解决方案!
  • 已添加。我为 userId 使用了一个整数,但如果你有字符串,这无关紧要。只有在我找到可行的解决方案后才记得。

标签: c# .net asp.net-mvc entity-framework asp.net-core


【解决方案1】:

既然您提到您正在使用 ASP.NET Core,我假设您也在使用 EF Core。不同之处在于,当您在 EF Core 中具有多对多关系时,您还需要在代码上创建“链接”实体。在 EF6 中,您不需要明确拥有该实体。无论如何,这是你可以做的:

创建链接实体:

public class MessageRecipients
{
    public int UserId { get; set; }

    public User User { get; set; }

    public int MessageId { get; set; }

    public Message Message { get; set; }
}

配置它们:

modelBuilder.Entity<MessageRecipients>()
    .HasKey(bc => new { bc.UserId, bc.MessageId });

modelBuilder.Entity<MessageRecipients>()
    .HasOne(bc => bc.User)
    .WithMany(b => b.Messages)
    .HasForeignKey(bc => bc.UserId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<MessageRecipients>()
    .HasOne(bc => bc.Message)
    .WithMany(c => c.Recipients)
    .HasForeignKey(bc => bc.MessageId)
    .OnDelete(DeleteBehavior.Restrict);

然后在您的POST 消息中,您可以这样做:

[HttpPost]
public async Task<IActionResult> PostMessage([FromBody] MessageViewModel viewModel)
{
    var message = new Message
    {
        MessageBody = viewModel.MessageBody,
        Recipients = viewModel.Users.Select(c => new MessageRecipients { UserId = c}).ToList()
    };

    _context.Messages.Add(message);
    await _context.SaveChangesAsync();

    return Ok();
}

public class MessageViewModel
{
    public string MessageBody { get; set; }

    public IEnumerable<int> Users { get; set; }
}

这将相应地填充多对多表:

【讨论】:

    猜你喜欢
    • 2015-02-16
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多