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
相关产品推荐
相关产品推荐

