2017-02-20 1 views
2

J'essaie de renvoyer un type personnalisé (composite) basé sur un type de table implicite.Comment renvoyer des types de tables personnalisés à partir de Npgsql et des procédures stockées?

J'ai cette définition de la table:

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

Ce qui est mis en correspondance avec cette définition de classe:

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

Ce qui est mis en correspondance en appelant:

NpgsqlConnection.MapCompositeGlobally<ApplicationUser>("app_user"); 

Et je suis en train pour renvoyer un enregistrement avec cette procédure stockée:

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; 

Ce que je vous appelle de C# comme ceci:

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

mais je reçois une exception lors de la coulée result-ApplicationUser:

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

Ceci est clairement parce que result est juste la chaîne Id , mais pourquoi n'est pas result mon objet composite app_user?

J'ai également essayé de retourner l'objet avec un paramètre out, mais j'ai rencontré exactement la même exception. Est ce que j'essaie de faire possible avec Npgsql, ou dois-je re-construire manuellement l'objet ApplicationUser en C# à partir des colonnes individuelles? Je utilise Npgsql v3.2.0 et PostgreSQL v9.6.

Répondre

1

On dirait que je l'ai compris. S'est avéré être plus facile que je ne le pensais. Tout ce que j'avais besoin de changer était la façon dont la procédure stockée était appelée depuis C#. Je préférais l'autre façon d'invoquer la procédure stockée, mais au moins cela fonctionne!