c# - 如何将复合类型传递给 PL/pgsql 函数?
问题描述
我正在尝试(不成功)将 PostgreSql 复合类型传递给 PL/pgsql 函数。下面列出了错误消息和示例代码。我还尝试了几种不同的代码变体(例如没有成功 - 每个版本都会生成不同的错误消息)。我是 SQL 新手,希望我犯了一个简单的错误。如果有人可以查看下面的示例代码并解释我犯了什么错误,我将不胜感激。
错误信息
System.InvalidCastException:指定 NpgsqlDbType.Enum 时,必须同时指定 SpecificType 在 Npgsql.TypeHandlerRegistry.get_Item(NpgsqlDbType npgsqlDbType,类型 specificType) 在 Npgsql.NpgsqlParameter.ResolveHandler(TypeHandlerRegistry 注册表) 在 Npgsql.NpgsqlParameter.Bind(TypeHandlerRegistry 注册表) 在 Npgsql.NpgsqlCommand.ValidateParameters() 在 Npgsql.NpgsqlCommand.d__71.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult() 在 Npgsql.NpgsqlCommand.d__87.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult() 在 Npgsql.NpgsqlCommand.ExecuteScalar() 在 F:\Visual Studio 2017\Projects\TestDatabase\TestDatabase\TestCompositeType.cs:line 42 中的 TestDatabase.TestCompositeType.Test() 在 F:\Visual Studio 2017\Projects\TestDatabase\TestDatabase\Program.cs:line 17 中的 TestDatabase.Program.Main(String[] args)
系统信息
Windows 10、64 位 PostgreSQL 10.3,由 Visual C++ build 1800 编译,64 位 Npgsql,版本=3.2.6.0
PostgreSql 代码
如果不存在 MySchema,则创建模式; 创建类型 MySchema.MyType as( X真实, Y 实数 ); 如果不存在则创建表 MySchema.MyTable( ItemID int 主键默认生成为identity, MyType MySchema.MyType ); 创建或替换函数 MySchema.SetMyType( ItemID2 整数, MyType2 MySchema.MyType ) 返回整数 作为$$ 宣布 结果ID int; 开始 结果ID:=项目ID2; 如果(存在(从 MySchema.MyTable 中选择 1 作为 mt 其中 mt.ItemID = ItemID2))然后 插入 MySchema.MyTable( MyType ) 值( MyType2 ) 将 mt.ItemID 返回到 resultID; 别的 将 MySchema.MyTable 更新为 mt 设置 MyType = MyType2 其中 mt.ItemID = ItemID2; 万一; 返回结果ID; 结尾; $$ 语言 plpgsql;
C# 代码
公共无效测试() { NpgsqlConnection.MapCompositeGlobally("MySchema.MyType"); var connection = new NpgsqlConnection("Host=localhost;Username=postgres;Password=123456;database=testdb"); 如果(空==连接) throw new NullReferenceException("connection"); 尝试 { 连接.打开(); var cmd = new NpgsqlCommand("MySchema.SetMyType", connection); cmd.CommandType = System.Data.CommandType.StoredProcedure; var par = new NpgsqlParameter("ItemID2", NpgsqlDbType.Integer); par.Value = 1; cmd.Parameters.Add(par); par = new NpgsqlParameter("MyType2", NpgsqlDbType.Composite); 我的类型我的类型 = 新的我的类型(); 我的类型.X = 1; 我的类型.Y = 2; par.Value = myType; cmd.Parameters.Add(par); int id = Convert.ToInt32( cmd.ExecuteScalar() ); } 最后 { 连接。关闭(); } }
解决方案
'sticky bit' 提出的建议纠正了这个问题。我在下面为可能处理相同问题的任何其他人提供了更新的示例代码。使用“ToLower()”将所有字符串转换为小写,但这仅在映射“NpgsqlConnection.MapCompositeGlobally”中的数据库类型时是必需的。
命名空间测试数据库 { 公共类 MyType { 公众持股量 X; 公众持股量 Y; }; 公共类 TestCompositeType { 公共无效测试() { NpgsqlConnection.MapCompositeGlobally<TestDatabase.MyType>("MySchema.MyType".ToLower()); var connection = new NpgsqlConnection("Host=localhost;Username=postgres;Password=123456;database=testdb".ToLower()); 如果(空==连接) throw new NullReferenceException("connection"); 尝试 { 连接.打开(); var cmd = new NpgsqlCommand("MySchema.SetMyType".ToLower(), 连接); cmd.CommandType = System.Data.CommandType.StoredProcedure; var par = new NpgsqlParameter("ItemID2".ToLower(), NpgsqlDbType.Integer); par.Value = 1; cmd.Parameters.Add(par); par = new NpgsqlParameter("MyType2".ToLower(), NpgsqlDbType.Composite); 我的类型我的类型 = 新的我的类型(); 我的类型.X = 1; 我的类型.Y = 2; par.Value = myType; par.SpecificType = typeof( MyType ); cmd.Parameters.Add(par); int id = Convert.ToInt32( cmd.ExecuteScalar() ); } 最后 { 连接。关闭(); } } } }
推荐阅读
- php - PHP | 输入控制语句不起作用
- sql - SQL Server 月末
- sql - 产品单价频繁变化时创建库存数据库
- string - 在 url 中使用字符串查询但指定字段集的自动填充复选框
- mysql - 从其他表更新 db avg 值中的字段
- vue.js - 如何让我的 v-show 在 Vue JS 中显示组件
- java - 无法弄清楚为什么我的选择排序作为 java 方法的实现不能按预期工作
- jquery - 使用 JQuery 向表单添加元素会导致提交时出现“无法解密防伪令牌”错误
- html - 仅设置图像高度属性在 HTML 中不起作用,但仅设置宽度属性有效
- docker - 无法在 Bitnami Dokuwiki 上创建用户