如何将参数传递给postgre函数并使用ExecuteReader获取数据?

时间:2017-06-09 17:22:45

标签: c# postgresql npgsql

我正在尝试使用C#application中的ExecuteReader从表中检索所有列.Db是postgre.To测试我创建了一个控制台应用程序,后面的教程确实展示了如何使用Function查询,但没有传递参数。用于测试的控制台应用程序功能

    static void Main(string[] args)
    {
        // Connect to a PostgreSQL database
        NpgsqlConnection conn = new NpgsqlConnection("Server=localhost;User Id=postgres; " +
            "Password=pes;Database=pmc;");
        conn.Open();

        // Define a query
        NpgsqlCommand command = new NpgsqlCommand("SELECT * from audit.exception_gl_accounts()", conn);

        // Execute the query and obtain a result set
        NpgsqlDataReader dr = command.ExecuteReader();

        // Output rows
        while (dr.Read())
            Console.Write("{0}\t{1} \n", dr[0], dr[1]);

        conn.Close();
    }
}

这里在NpgsqlCommand中我将没有参数的查询发送到函数audit.exception_gl_accounts,它运行良好。现在如何将参数传递给这样的函数

  

“SELECT * FROM sms.get_accounts_info(@AccountNumber);

我正在尝试使用此函数检索所有5列并获取这些对象

    public static string GetAccountInfo(string accountNumber)
    {
        NpgsqlConnection conn = new NpgsqlConnection("Server=localhost;User 
                            Id=postgres; " + "Password=pes;Database=pmc;");
        conn.Open();
        NpgsqlCommand command = new NpgsqlCommand("SELECT * FROM 
                           sms.get_accounts_info(@AccountNumber); ", conn);
        command.Parameters.AddWithValue("@AccountNumber", accountNumber);
        NpgsqlDataReader dr = command.ExecuteReader();
        while (dr.Read())
            Console.Write("{0}\t{1} \n", dr[0], dr[1]);
            return dr.ToString();
    }

使用第二个示例代码会出现此错误:

  

{     “accountNumber”:“Npgsql.ForwardsOnlyDataReader”,     “balance”:null,     “interestRate”:0,     “accountName”:null,     “accountType”:null   }

感谢任何帮助。

详细信息

控制器

[HttpPost]
[ActionName("info")]
public IHttpActionResult GetAccountInfo([FromBody]AccountInfo 
accountinfo)
 {
accountinfo.accountNumber = BusinessLayer.Api.AccountHolderApi.GetAccountInfo
          (accountinfo.accountNumber);
            return Ok(accountinfo);
 }

帐户信息类

public class AccountInfo
    {
      public string accountNumber { get; set; }
      public string balance { get; set; }
      public int interestRate { get; set; }
      public string accountName { get; set; }
      public string accountType { get; set; }
    }

URI

  

http://localhost:8080/v1/accounts/info

GetAccountsInfo

CREATE OR REPLACE FUNCTION sms.get_accounts_info(IN account_number_ character varying)
  RETURNS TABLE(account_number character varying, account_name text, product character varying, interest_rate numeric, balance money) AS
$BODY$
BEGIN
    RETURN QUERY(
        SELECT a.account_number,
        c.customer_name,
            p.deposit_product_name, 
            a.interest_rate::numeric, deposit.get_balance(account_number_)
        FROM deposit.account_holders a 
        JOIN core.customers_view  c ON a.customer_id = c.customer_id
        JOIN core.deposit_products p ON a.deposit_product_id = p.deposit_product_id
        WHERE a.account_number = $1
    );
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION sms.get_accounts_info(character varying)
  OWNER TO postgres;

1 个答案:

答案 0 :(得分:2)

如果没有实体框架,您需要将从datareader读取值的代码编写到private void SubjectsList_Loaded(object sender, RoutedEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => ColorMyRows())); } 类的实例中:

AccountInfo

请注意,函数的返回类型已更改为public static AccountInfo GetAccountInfo(string accountNumber) { AccountInfo result = null; using(var conn = new NpgsqlConnection("...")) { conn.Open(); using(var command = new NpgsqlCommand("SELECT * FROM sms.get_accounts_info(@AccountNumber); ", conn)) { command.Parameters.AddWithValue("@AccountNumber", accountNumber); using(var dr = command.ExecuteReader()) { if(dr.HasRows && dr.Read()) { result = new AccountInfo { accountNumber = dr["accountNumber"].ToString(), balance = dr["balance"].ToString(), interestRate = Convert.ToInt32(dr["interestRate"]), accountName = dr["accountName"].ToString() }; } } } } return result; } ,之前为字符串。此外,它仅限于读取一条记录,如果对AccountInfo的一次调用可以返回多条记录,则情况就不同了。我只是假设sms.get_accounts_infoaccount_number表中的主键。

有些细节需要你注意,例如account_holders是数据库中的钱,但是类中的字符串。另外我不知道balance(数据库)和product(类)是否以及如何对应,所以我省略了它。

数据库连接,命令和数据引用程序为accountType,应包含在IDisposable块中。