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

EF Core调用PostgreSQL存储过程报错:输出参数引用问题

解决EF Core调用PostgreSQL带OUT参数函数的报错问题

问题根源

PostgreSQL的FUNCTION和PROCEDURE在EF Core中的参数处理逻辑不同,你遇到的报错是因为.NET调用代码错误地将OUT参数作为SQL语句的占位符引用,而EF Core会将其识别为仅输出参数,不允许在SQL中作为输入参数使用。

解决方案

1. 确认函数类型并修正调用方式

情况1:你的对象是PostgreSQL FUNCTION(存储函数)

PostgreSQL的FUNCTION带OUT参数时,OUT参数是函数返回值的一部分,调用时不需要在SQL中显式传递OUT参数。

修正后的.NET调用代码:

  • 单OUT参数场景,直接查询返回值:
var userId = 1;
var topicId = 2;

// 方式1:映射到基础类型
var totalScore = context.Set<int>()
    .FromSqlRaw("SELECT user_topic_total_score_procedure({0}, {1})", userId, topicId)
    .FirstOrDefault();

// 方式2:自定义实体类适配多OUT参数
// 先定义结果实体
public class ScoreResult
{
    public int Score { get; set; }
}

// 在DbContext中添加无表映射的DbSet
public DbSet<ScoreResult> ScoreResults { get; set; }

// 调用查询
var result = context.ScoreResults
    .FromSqlRaw("SELECT * FROM user_topic_total_score_procedure({0}, {1})", userId, topicId)
    .FirstOrDefault();
var totalScore = result?.Score;

情况2:你的对象是PostgreSQL PROCEDURE(存储过程)

如果是PROCEDURE,需要用CALL语句调用,且OUT参数需显式配置为输出方向,推荐直接使用NpgsqlCommand避免EF Core参数映射冲突:

var userId = 1;
var topicId = 2;

using var connection = context.Database.GetDbConnection();
await connection.OpenAsync();
using var command = connection.CreateCommand();

command.CommandText = "CALL user_topic_total_score_procedure(@userId, @topicId, @score)";
command.Parameters.Add(new NpgsqlParameter("userId", userId));
command.Parameters.Add(new NpgsqlParameter("topicId", topicId));

// 配置OUT参数
var scoreParam = new NpgsqlParameter("score", NpgsqlDbType.Integer) 
{ 
    Direction = ParameterDirection.Output 
};
command.Parameters.Add(scoreParam);

await command.ExecuteNonQueryAsync();
var totalScore = (int)scoreParam.Value;

2. 迁移代码的检查与优化

确保迁移中创建的函数/存储过程定义正确,示例FUNCTION定义:

CREATE OR REPLACE FUNCTION user_topic_total_score_procedure(
    user_id INT, 
    topic_id INT, 
    OUT score INT
)
AS $$
BEGIN
    SELECT COALESCE(SUM(s.score), 0) INTO score 
    FROM user_scores s 
    WHERE s.user_id = $1 AND s.topic_id = $2;
END;
$$ LANGUAGE plpgsql;
  • 用COALESCE避免返回NULL,防止后续类型转换报错。

3. 版本兼容性检查

确保Npgsql.EntityFrameworkCore.PostgreSQL版本与PostgreSQL服务器版本匹配(推荐使用最新稳定版),旧版本对PROCEDURE的OUT参数支持可能存在缺陷。

内容的提问来源于stack exchange,提问作者Mehmed Emre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:58:26