I'm trying to return a custom (composite) type based on an implicit table type.
I have this table definition:
CREATE TABLE app_user (id CHAR(36) PRIMARY KEY, name TEXT);
Which is mapped to this class definition:
public class ApplicationUser
{
public string Id { get; set; }
public string Name { get; set; }
}
Which is mapped by calling:
NpgsqlConnection.MapCompositeGlobally<ApplicationUser>("app_user");
And I'm trying to return a record with this stored procedure:
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;
Which I'm calling from C# like this:
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;
}
}
But I get an exception when casting result
to ApplicationUser
:
InvalidCastException: Unable to cast object of type 'System.String' to type 'MyApp.ApplicationUser'.
This is clearly because result
is just the string Id
, but why isn't result
my composite app_user
object?
I've also tried to return the object with an out parameter, but ran into the exact same exception. Is what I'm trying to do possible with Npgsql, or do I have to re-build the ApplicationUser
object manually in C# from the individual columns?
I'm using Npgsql v3.2.0 and PostgreSQL v9.6.
Looks like I figured it out. Turned out to be easier than I thought. All I needed to change was the way the stored procedure was called from C#.
I preferred the other way of invoking the stored procedure, but at least this works!