【问题标题】:Insert record into DB in one to many relation model在一对多关系模型中将记录插入数据库
【发布时间】:2022-01-09 00:48:39
【问题描述】:

我刚刚开始使用 SQL,并试图让我的第一个示例正常工作。我有两个具有一对多关系的表:

public class Customer
{
    public Guid Id { get; set; }
    public string CompanyName { get; set; }
    public string Address { get; set; }
    public virtual ICollection<Project> Projects { get; set; }
}

public class Project
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string ProjectType { get; set; }
    public Customer Customer { get; set; }
}

然后我通过 API ProjectsController 执行以下命令:

[HttpPost]
public async Task<IActionResult> Post(Project project)
{
    Customer newCustomer = _context.Customers
                                   .FirstOrDefault(c => c.Id == project.Customer.Id);

    Project newProject = new Project
                             {
                                 Name = project.Name,
                                 ProjectType = project.ProjectType,
                                 Customer = newCustomer,
                             };

    _context.Projects.Add(newProject);

    await _context.SaveChangesAsync();

    return Ok(newProject.Id);
}

但是,由于我在数据库中已经有一个具有此 ID 的客户,所以我遇到了一个异常(在创建新项目时,无需创建新客户;客户是从项目创建对话框的下拉框中选择的) :

Microsoft.EntityFrameworkCore.DbUpdateException:保存实体更改时出错。有关详细信息,请参阅内部异常。

Microsoft.Data.SqlClient.SqlException (0x80131904):违反主键约束“PK_ProjectStates”。无法在对象“dbo.ProjectStates”中插入重复键。重复键值为 (057cfca4-934b-40a4-a3f8-44840e532f4a)。声明已终止。

如何正确地做到这一点?

【问题讨论】:

标签: c# sql linq


【解决方案1】:

您应该为您的项目实体添加 CustomerId 属性,使其如下所示:

public class Project
  {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string ProjectType { get; set; }
    public Guid CustomerId { get; set; }
    public Customer Customer { get; set; }
  }

然后,当您添加新项目时,您传递的是 CustomerId 而没有传递 Customer 对象 - 例如,如果您想获取包含 Customer 的项目信息,它只是导航属性。

[HttpPost]
public async Task<IActionResult> Post(Project project)
{
  //You can use FirstOrDefaultAsync here
  Customer newCustomer = await _context.Customers.FirstOrDefaultAsync(c => c.Id == project.CustomerId);

  // You should also add validation here because when there is no customer with that id, you'll recive NullReferenceException while assigning CustomerId so you can add something like this
  if(newCustomer is null)
  {
    return NotFound();  
  }

  Project newProject = new Project
  {
    Name = project.Name,
    ProjectType = project.ProjectType,
    CustomerId = newCustomer.Id,
  };

  //You can use AddAsync here
  await _context.Projects.AddAsync(newProject); 
  await _context.SaveChangesAsync();
  return Ok(newProject.Id);
}

【讨论】:

    【解决方案2】:

    试试这个,把_context.Projects.Add(newProject);改成 newCustomer.Projects.Add(newProject);

    此外,在我们向现有客户添加/分配项目时,请删除 Customer = newCustomer, 分配。

    总的来说,您的新方法看起来像这样。 (以上两处改动)

    [HttpPost]
    public async Task<IActionResult> Post(Project project)
    {
        Customer newCustomer = _context.Customers
                                       .FirstOrDefault(c => c.Id == project.Customer.Id);
    
        Project newProject = new Project
                                 {
                                     Name = project.Name,
                                     ProjectType = project.ProjectType
                                 };
    
        newCustomer.Projects.Add(newProject);
    
        await _context.SaveChangesAsync();
    
        return Ok(newProject.Id);
    }
    

    希望您了解具体是什么变化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多