2017-02-20 3 views
2

Я пытаюсь вернуть пользовательский (составной) тип на основе неявного типа таблицы.Как вернуть пользовательские типы таблиц из 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<ApplicationUser>("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; 
    } 
} 

Но я получаю исключение при заливке result к ApplicationUser:

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

Это ясно, потому что result просто строка Id , но почему не result мой составной app_user объект?

Я также попытался вернуть объект с параметром out, но столкнулся с тем же исключением. Я пытаюсь сделать это с помощью Npgsql, или мне нужно повторно построить объект ApplicationUser вручную на C# из отдельных столбцов?

Я использую Npgsql v3.2.0 и PostgreSQL v9.6.

ответ

1

Похоже, я понял. Оказалось, было легче, чем я думал. Все, что мне нужно было изменить, - это способ, с которого была вызвана хранимая процедура с 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; 
    } 
} 

Я предпочел другой способ вызова хранимой процедуры, но по крайней мере это работает!

Смежные вопросы