You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core调用存储过程执行Post请求时出现System.InvalidOperationException:FromSql操作结果缺少必填列'EmpID'的问题求助

解决EF Core调用存储过程插入数据时的EmpID缺失错误

首先,咱们来定位你遇到的错误根源:

Exception : System.InvalidOperationException: The required column 'EmpID' was not present in the results of a 'FromSql' operation.

这个错误的核心原因是:你用了FromSqlRaw来执行插入型的存储过程,但EF Core的FromSqlRaw是为查询操作设计的——它期望存储过程返回的结果集能完整映射到EmployeeDetails实体,而你的存储过程只做了数据插入,没有返回任何包含EmpID的结果集。加上EmployeeDetails里的EmpID被标记为[Key],EF Core会强制要求结果集里必须有这个列,所以就抛出了错误。

接下来给你分步解决的方案:

1. 替换执行存储过程的方式(核心修复)

把执行插入存储过程的代码从FromSqlRaw改成ExecuteSqlRawAsync——这是EF Core专门用来执行非查询操作(插入、更新、删除)的方法,不会要求返回结果集映射到实体。

修改控制器里的这段代码:

// 原来错误的写法
await _context.EmployeeDetails.FromSqlRaw(StoredProc).ToListAsync();

// 改为正确的非查询执行方式
await _context.Database.ExecuteSqlRawAsync(StoredProc);

2. 修复SQL注入风险(重要优化)

你现在直接拼接字符串生成存储过程调用语句,存在严重的SQL注入风险。应该改用参数化的方式传递参数:

// 用参数化查询替换字符串拼接
var storedProc = "EXEC PROC_INSERTEMPLOYEEDETAILS @FirstName, @LastName, @Status, @Age, @Designation, @Salary, @DoorNo, @StreetName, @Area, @City, @State, @ContactNo, @EmailID, @Qualification, @Experience, @FormerCompany, @AwardsAndTitles";

await _context.Database.ExecuteSqlRawAsync(
    storedProc,
    new SqlParameter("@FirstName", id.FirstName),
    new SqlParameter("@LastName", id.LastName),
    new SqlParameter("@Status", id.Status),
    new SqlParameter("@Age", id.Age),
    new SqlParameter("@Designation", id.Designation),
    new SqlParameter("@Salary", id.Salary),
    new SqlParameter("@DoorNo", id.DoorNo),
    new SqlParameter("@StreetName", id.StreetName),
    new SqlParameter("@Area", id.Area),
    new SqlParameter("@City", id.City),
    new SqlParameter("@State", id.State),
    new SqlParameter("@ContactNo", id.ContactNo),
    new SqlParameter("@EmailID", id.EmailID),
    new SqlParameter("@Qualification", id.Qualification),
    new SqlParameter("@Experience", id.Experience),
    new SqlParameter("@FormerCompany", id.FormerCompany),
    new SqlParameter("@AwardsAndTitles", id.AwardsAndTitles)
);

3. 修复存储过程的事务处理(可选但推荐)

你的存储过程CATCH块里的逻辑有问题:当XACT_STATE() = 1时,说明事务是可提交的,但如果已经进入CATCH块,说明发生了错误,应该回滚而不是提交。修正后的CATCH块:

BEGIN CATCH
    IF (XACT_STATE()) <> 0
        BEGIN
            ROLLBACK TRANSACTION
        END
    SELECT 'Error' = @@ERROR
END CATCH

4. 优化输入模型的EmpID定义

你的EmployeeDetails模型里EmpID是字段(没有get;set;),虽然标记了[JsonIgnore],但EF Core实体映射通常要求属性(带getter/setter),建议改成:

[Key]
[JsonIgnore]
public string EmpID { get; set; }

最终的控制器代码片段

修改后的GetEmployeeDetails1方法大概是这样:

[Route("AddEmployee")]
[HttpPost]
public async Task<ActionResult<IEnumerable<EmployeeDet>>> GetEmployeeDetails1([FromBody] EmployeeDetails id)
{
    try
    {
        // 参数化存储过程调用
        var storedProc = "EXEC PROC_INSERTEMPLOYEEDETAILS @FirstName, @LastName, @Status, @Age, @Designation, @Salary, @DoorNo, @StreetName, @Area, @City, @State, @ContactNo, @EmailID, @Qualification, @Experience, @FormerCompany, @AwardsAndTitles";

        await _context.Database.ExecuteSqlRawAsync(
            storedProc,
            new SqlParameter("@FirstName", id.FirstName),
            new SqlParameter("@LastName", id.LastName),
            new SqlParameter("@Status", id.Status),
            new SqlParameter("@Age", id.Age),
            new SqlParameter("@Designation", id.Designation),
            new SqlParameter("@Salary", id.Salary),
            new SqlParameter("@DoorNo", id.DoorNo),
            new SqlParameter("@StreetName", id.StreetName),
            new SqlParameter("@Area", id.Area),
            new SqlParameter("@City", id.City),
            new SqlParameter("@State", id.State),
            new SqlParameter("@ContactNo", id.ContactNo),
            new SqlParameter("@EmailID", id.EmailID),
            new SqlParameter("@Qualification", id.Qualification),
            new SqlParameter("@Experience", id.Experience),
            new SqlParameter("@FormerCompany", id.FormerCompany),
            new SqlParameter("@AwardsAndTitles", id.AwardsAndTitles)
        );

        // 查询最新插入的员工数据(修正原SQL的语法错误)
        return await _context.EmployeeDetails.FromSqlRaw("SELECT TOP 1 * FROM EmployeeDetails ORDER BY EmpID DESC").ToListAsync();
    }
    catch(Exception ex)
    {
        return Ok("Exception : " + ex);
    }
}

另外,注意你原代码里的查询语句Select Top 1 FROM EmployeeDetails有语法错误,少了*或者列名,已经修正为SELECT TOP 1 * FROM EmployeeDetails ORDER BY EmpID DESC。

按照这些步骤修改后,你的插入操作应该就能正常执行,不会再出现EmpID缺失的错误了。

内容的提问来源于stack exchange,提问作者Priyadharshini Charles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 13:02:30