如何从Npgsql和存储过程返回自定义表类型?

我正在尝试基于隐式表类型返回自定义(复合)类型。

我有这个表定义:

CREATE TABLE app_user (id CHAR(36) PRIMARY KEY, name TEXT); 

哪个映射到此类定义:

 public class ApplicationUser { public string Id { get; set; } public string Name { get; set; } } 

通过调用映射:

 NpgsqlConnection.MapCompositeGlobally("app_user"); 

我正在尝试使用此存储过程返回记录:

 CREATE FUNCTION find_by_id(user_id app_user.id%TYPE) RETURNS app_user AS $$ DECLARE found_user app_user; BEGIN SELECT * FROM app_user WHERE id = user_id INTO found_user; RETURN found_user; END $$ LANGUAGE plpgsql STABLE SECURITY DEFINER; 

我从C#调用的是这样的:

 ApplicationUser user; using (NpgsqlConnection db = new NpgsqlConnection(this.connectionString)) { db.Open(); using (NpgsqlCommand cmd = new NpgsqlCommand("find_by_id", db)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("user_id", userId); object result = cmd.ExecuteScalar(); user = result == DBNull.Value ? null : (ApplicationUser)result; } } 

但是在将resultApplicationUser时出现exception:

 InvalidCastException: Unable to cast object of type 'System.String' to type 'MyApp.ApplicationUser'. 

这显然是因为result只是字符串Id ,但为什么不是我的复合app_user对象的result呢?

我也尝试使用out参数返回对象,但遇到了完全相同的exception。 我正在尝试使用Npgsql做什么,或者我是否必须在C#中从各个列手动重新构建ApplicationUser对象?

我正在使用Npgsql v3.2.0和PostgreSQL v9.6。

看起来我想通了。 结果比我想象的要容易。 我需要改变的是从C#调用存储过程的方式。

 ApplicationUser user; using (NpgsqlConnection db = new NpgsqlConnection(this.connectionString)) { db.Open(); using (NpgsqlCommand cmd = new NpgsqlCommand("SELECT find_by_id(@user_id);", db)) { cmd.Parameters.AddWithValue("user_id", userId); object result = cmd.ExecuteScalar(); user = result == DBNull.Value ? null : (ApplicationUser)result; } } 

我更喜欢调用存储过程的另一种方式,但至少这是有效的!