在.NET Core中创建含两个外键的模型类与控制器(Assign中间表开发)
适配现有手写SQL风格的多对多关联实现方案
1. 新增Assign中间表模型类
完全对齐你现有Consultant、Project模型的简洁POCO风格,不需要硬套EF Core导航属性,直接定义对应字段即可:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace WebAPI_C5.Models { public class Assign { // 自增主键,方便CRUD操作定位单条记录 public int AssignId { get; set; } // 关联Consultant表的外键字段 public int ConsultantId { get; set; } // 关联Project表的外键字段 public int ProjectId { get; set; } } }
对应的数据库中间表建表参考SQL:
CREATE TABLE dbo.Assign( AssignId int PRIMARY KEY IDENTITY(1,1), ConsultantId int NOT NULL, ProjectId int NOT NULL, -- 外键参照约束,保证关联数据完整性 FOREIGN KEY (ConsultantId) REFERENCES dbo.Consultant(ConsultantId), FOREIGN KEY (ProjectId) REFERENCES dbo.Project(ProjectId), -- 唯一约束,避免同一顾问重复绑定到同一项目 CONSTRAINT UQ_Assign_Consultant_Project UNIQUE(ConsultantId, ProjectId) )
2. 新增AssignController控制器
完全沿用你现有ConsultantController的编码模式,通过依赖注入读取连接字符串,手写SQL完成CRUD操作,同时修正你原有代码直接拼接SQL的SQL注入问题,代码如下:
using Microsoft.AspNetCore.Mvc; using System.Data; using System.Data.SqlClient; namespace WebAPI_C5.Controllers { [Route("api/[controller]")] [ApiController] public class AssignController : ControllerBase { private readonly IConfiguration _configuration; public AssignController(IConfiguration configuration) { _configuration = configuration; } // 获取全部分配关联,联表返回关联的顾问、项目名称 [HttpGet] public JsonResult Get() { string query = @" SELECT a.AssignId, a.ConsultantId, c.ConsultantName, a.ProjectId, p.ProjectName FROM dbo.Assign a LEFT JOIN dbo.Consultant c ON a.ConsultantId = c.ConsultantId LEFT JOIN dbo.Project p ON a.ProjectId = p.ProjectId "; DataTable table = new DataTable(); string sqlDataSource = _configuration.GetConnectionString("ProjectAppCon"); using (SqlConnection myCon = new SqlConnection(sqlDataSource)) { myCon.Open(); using (SqlCommand myCommand = new SqlCommand(query, myCon)) { SqlDataReader myReader = myCommand.ExecuteReader(); table.Load(myReader); } } return new JsonResult(table); } // 新增绑定:将顾问和项目关联起来 [HttpPost] public JsonResult Post(Assign assign) { // 使用参数化查询替代字符串拼接,避免SQL注入 string query = @" INSERT INTO dbo.Assign (ConsultantId, ProjectId) VALUES (@ConsultantId, @ProjectId) "; string sqlDataSource = _configuration.GetConnectionString("ProjectAppCon"); using (SqlConnection myCon = new SqlConnection(sqlDataSource)) { myCon.Open(); using (SqlCommand myCommand = new SqlCommand(query, myCon)) { myCommand.Parameters.AddWithValue("@ConsultantId", assign.ConsultantId); myCommand.Parameters.AddWithValue("@ProjectId", assign.ProjectId); myCommand.ExecuteNonQuery(); } } return new JsonResult("分配关系添加成功"); } // 更新绑定:调整某条关联记录对应的顾问或项目 [HttpPut] public JsonResult Put(Assign assign) { string query = @" UPDATE dbo.Assign SET ConsultantId = @ConsultantId, ProjectId = @ProjectId WHERE AssignId = @AssignId "; string sqlDataSource = _configuration.GetConnectionString("ProjectAppCon"); using (SqlConnection myCon = new SqlConnection(sqlDataSource)) { myCon.Open(); using (SqlCommand myCommand = new SqlCommand(query, myCon)) { myCommand.Parameters.AddWithValue("@AssignId", assign.AssignId); myCommand.Parameters.AddWithValue("@ConsultantId", assign.ConsultantId); myCommand.Parameters.AddWithValue("@ProjectId", assign.ProjectId); myCommand.ExecuteNonQuery(); } } return new JsonResult("分配关系更新成功"); } // 删除绑定:解除顾问和项目的关联 [HttpDelete("{id}")] public JsonResult Delete(int id) { string query = @" DELETE FROM dbo.Assign WHERE AssignId = @AssignId "; string sqlDataSource = _configuration.GetConnectionString("ProjectAppCon"); using (SqlConnection myCon = new SqlConnection(sqlDataSource)) { myCon.Open(); using (SqlCommand myCommand = new SqlCommand(query, myCon)) { myCommand.Parameters.AddWithValue("@AssignId", id); myCommand.ExecuteNonQuery(); } } return new JsonResult("分配关系删除成功"); } } }
3. 后续使用说明
- 你原有
ConsultantController、ProjectController中直接拼接SQL字符串的写法存在SQL注入风险,后续可以参照上面的参数化写法逐步替换原有拼接逻辑,不需要大改现有代码结构 - 要查询某项目下的所有关联顾问、或某顾问参与的所有项目,直接通过Assign表做关联查询即可,不需要写复杂的跨表逻辑,比如查询某顾问参与的项目:
SELECT p.* FROM dbo.Project p INNER JOIN dbo.Assign a ON p.ProjectId = a.ProjectId WHERE a.ConsultantId = @传入的顾问ID - 中间表的唯一约束可以从数据库层面避免重复绑定的无效数据,不需要在后端写额外的判重逻辑
内容的提问来源于stack exchange,提问作者user9510048
相关产品推荐
相关产品推荐

