How to return custom table types from Npgsql and stored procedures?

喜你入骨 提交于 2019-12-01 09:42:01

问题


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.


回答1:


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#.

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;
    }
}

I preferred the other way of invoking the stored procedure, but at least this works!



来源:https://stackoverflow.com/questions/42337076/how-to-return-custom-table-types-from-npgsql-and-stored-procedures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!