Skip to content

Commit dab9657

Browse files
authored
Merge pull request #202284 from jonels-msft/hyperscale-citus-app-stacks
Hyperscale citus app stacks
2 parents 57f6248 + b369be7 commit dab9657

15 files changed

+1794
-8
lines changed

articles/postgresql/TOC.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,20 @@
689689
items:
690690
- name: Connect and query
691691
href: hyperscale/howto-connect.md
692+
- name: App stacks
693+
items:
694+
- name: Overview
695+
href: hyperscale/howto-app-stacks-overview.md
696+
- name: Python
697+
href: hyperscale/howto-app-stacks-python.md
698+
- name: Node.js
699+
href: hyperscale/howto-app-stacks-nodejs.md
700+
- name: C#
701+
href: hyperscale/howto-app-stacks-csharp.md
702+
- name: Java
703+
href: hyperscale/howto-app-stacks-java.md
704+
- name: Ruby
705+
href: hyperscale/howto-app-stacks-ruby.md
692706
- name: Build scalable apps
693707
items:
694708
- name: Overview
Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
---
2+
title: C# app to connect and query Hyperscale (Citus)
3+
description: Learn to query Hyperscale (Citus) using C#
4+
ms.author: sasriram
5+
author: saimicrosoft
6+
ms.service: postgresql
7+
ms.subservice: hyperscale-citus
8+
ms.topic: how-to
9+
ms.date: 06/20/2022
10+
---
11+
12+
# C# app to connect and query Hyperscale (Citus)
13+
14+
[!INCLUDE[applies-to-postgresql-hyperscale](../includes/applies-to-postgresql-hyperscale.md)]
15+
16+
In this document, you'll learn how to connect to a Hyperscale (Citus) database using a C# application. You'll see how to use SQL statements to query, insert, update, and delete data in the database. The steps in this article assume that you're familiar with developing using C#, and are new to working with Hyperscale (Citus).
17+
18+
> [!TIP]
19+
>
20+
> The process of creating a C# app with Hyperscale (Citus) is the same as working with ordinary PostgreSQL.
21+
22+
## Prerequisites
23+
24+
* An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free)
25+
* Create a Hyperscale (Citus) server group using this link [Create Hyperscale (Citus) server group](quickstart-create-portal.md)
26+
* Install the [.NET SDK](https://dotnet.microsoft.com/download) for your platform (Windows, Ubuntu Linux, or macOS) for your platform.
27+
* Install [Visual Studio](https://www.visualstudio.com/downloads/) to build your project.
28+
* Install the [Npgsql](https://www.nuget.org/packages/Npgsql/) NuGet package in Visual Studio.
29+
30+
## Get database connection information
31+
32+
To get the database credentials, you can use the **Connection strings** tab in the Azure portal. See below screenshot.
33+
34+
![Diagram showing C# connection string.](../media/howto-app-stacks/03-csharp-connection-string.png)
35+
36+
## Step 1: Connect, create table, and insert data
37+
38+
Use the following code to connect and load the data using CREATE TABLE and INSERT INTO SQL statements. The code uses these `NpgsqlCommand` class methods:
39+
40+
* [Open()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlConnection.html#Npgsql_NpgsqlConnection_Open) to establish a connection to Hyperscale (Citus),
41+
* [CreateCommand()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlConnection.html#Npgsql_NpgsqlConnection_CreateCommand) to set the CommandText property,
42+
* [ExecuteNonQuery()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlCommand.html#Npgsql_NpgsqlCommand_ExecuteNonQuery) to run database commands.
43+
44+
```csharp
45+
using System;
46+
using Npgsql;
47+
namespace Driver
48+
{
49+
public class AzurePostgresCreate
50+
{
51+
52+
static void Main(string[] args)
53+
{
54+
// Replace below argument with connection string from portal.
55+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host> Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
56+
57+
connStr.TrustServerCertificate = true;
58+
59+
using (var conn = new NpgsqlConnection(connStr.ToString()))
60+
{
61+
Console.Out.WriteLine("Opening connection");
62+
conn.Open();
63+
using (var command = new NpgsqlCommand("DROP TABLE IF EXISTS pharmacy;", conn))
64+
{
65+
command.ExecuteNonQuery();
66+
Console.Out.WriteLine("Finished dropping table (if existed)");
67+
}
68+
using (var command = new NpgsqlCommand("CREATE TABLE pharmacy (pharmacy_id integer ,pharmacy_name text,city text,state text,zip_code integer);", conn))
69+
{
70+
command.ExecuteNonQuery();
71+
Console.Out.WriteLine("Finished creating table");
72+
}
73+
using (var command = new NpgsqlCommand("CREATE INDEX idx_pharmacy_id ON pharmacy(pharmacy_id);", conn))
74+
{
75+
command.ExecuteNonQuery();
76+
Console.Out.WriteLine("Finished creating index");
77+
}
78+
using (var command = new NpgsqlCommand("INSERT INTO pharmacy (pharmacy_id,pharmacy_name,city,state,zip_code) VALUES (@n1, @q1, @a, @b, @c)", conn))
79+
{
80+
command.Parameters.AddWithValue("n1", 0);
81+
command.Parameters.AddWithValue("q1", "Target");
82+
command.Parameters.AddWithValue("a", "Sunnyvale");
83+
command.Parameters.AddWithValue("b", "California");
84+
command.Parameters.AddWithValue("c", 94001);
85+
int nRows = command.ExecuteNonQuery();
86+
Console.Out.WriteLine(String.Format("Number of rows inserted={0}", nRows));
87+
}
88+
89+
}
90+
Console.WriteLine("Press RETURN to exit");
91+
Console.ReadLine();
92+
}
93+
}
94+
}
95+
```
96+
97+
## Step 2: Use the super power of distributed tables
98+
99+
Hyperscale (Citus) gives you [the super power of distributing tables](overview.md#the-superpower-of-distributed-tables) across multiple nodes for scalability. The command below enables you to distribute a table. You can learn more about `create_distributed_table` and the distribution column [here](howto-build-scalable-apps-concepts.md#distribution-column-also-known-as-shard-key).
100+
101+
> [!TIP]
102+
>
103+
> Distributing your tables is optional if you are using the Basic Tier of Hyperscale (Citus), which is a single-node server group.
104+
105+
```csharp
106+
using System;
107+
using Npgsql;
108+
namespace Driver
109+
{
110+
public class AzurePostgresCreate
111+
{
112+
113+
static void Main(string[] args)
114+
{
115+
// Replace below argument with connection string from portal.
116+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
117+
118+
connStr.TrustServerCertificate = true;
119+
120+
using (var conn = new NpgsqlConnection(connStr.ToString()))
121+
{
122+
Console.Out.WriteLine("Opening connection");
123+
conn.Open();
124+
using (var command = new NpgsqlCommand("select create_distributed_table('pharmacy','pharmacy_id');", conn))
125+
{
126+
command.ExecuteNonQuery();
127+
Console.Out.WriteLine("Finished distributing the table");
128+
}
129+
130+
}
131+
Console.WriteLine("Press RETURN to exit");
132+
Console.ReadLine();
133+
}
134+
}
135+
}
136+
```
137+
138+
## Step 3: Read data
139+
140+
Use the following code to connect and read the data using a SELECT SQL statement. The code uses these `NpgsqlCommand` class methods:
141+
142+
* [Open()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlConnection.html#Npgsql_NpgsqlConnection_Open) to establish a connection to Hyperscale (Citus).
143+
* [CreateCommand()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlConnection.html#Npgsql_NpgsqlConnection_CreateCommand) and [ExecuteReader()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlCommand.html#Npgsql_NpgsqlCommand_ExecuteReader) to run the database commands.
144+
* [Read()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlDataReader.html#Npgsql_NpgsqlDataReader_Read) to advance to the record in the results.
145+
* [GetInt32()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlDataReader.html#Npgsql_NpgsqlDataReader_GetInt32_System_Int32_) and [GetString()](https://www.npgsql.org/doc/api/Npgsql.NpgsqlDataReader.html#Npgsql_NpgsqlDataReader_GetString_System_Int32_) to parse the values in the record.
146+
147+
```csharp
148+
using System;
149+
using Npgsql;
150+
namespace Driver
151+
{
152+
public class read
153+
{
154+
155+
static void Main(string[] args)
156+
{
157+
// Replace below argument with connection string from portal.
158+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
159+
160+
connStr.TrustServerCertificate = true;
161+
162+
using (var conn = new NpgsqlConnection(connString))
163+
{
164+
Console.Out.WriteLine("Opening connection");
165+
conn.Open();
166+
using (var command = new NpgsqlCommand("SELECT * FROM pharmacy", conn))
167+
{
168+
var reader = command.ExecuteReader();
169+
while (reader.Read())
170+
{
171+
Console.WriteLine(
172+
string.Format(
173+
"Reading from table=({0}, {1}, {2}, {3}, {4})",
174+
reader.GetInt32(0).ToString(),
175+
reader.GetString(1),
176+
reader.GetString(2),
177+
reader.GetString(3),
178+
reader.GetInt32(4).ToString()
179+
)
180+
);
181+
}
182+
reader.Close();
183+
}
184+
}
185+
Console.WriteLine("Press RETURN to exit");
186+
Console.ReadLine();
187+
}
188+
}
189+
}
190+
```
191+
192+
## Step 4: Update data
193+
194+
Use the following code to connect and update data using an UPDATE SQL statement.
195+
196+
```csharp
197+
using System;
198+
using Npgsql;
199+
namespace Driver
200+
{
201+
public class AzurePostgresUpdate
202+
{
203+
static void Main(string[] args)
204+
{
205+
// Replace below argument with connection string from portal.
206+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
207+
208+
connStr.TrustServerCertificate = true;
209+
210+
using (var conn = new NpgsqlConnection(connStr.ToString()))
211+
{
212+
Console.Out.WriteLine("Opening connection");
213+
conn.Open();
214+
using (var command = new NpgsqlCommand("UPDATE pharmacy SET city = @q WHERE pharmacy_id = @n", conn))
215+
{
216+
command.Parameters.AddWithValue("n", 0);
217+
command.Parameters.AddWithValue("q", "guntur");
218+
int nRows = command.ExecuteNonQuery();
219+
Console.Out.WriteLine(String.Format("Number of rows updated={0}", nRows));
220+
}
221+
}
222+
Console.WriteLine("Press RETURN to exit");
223+
Console.ReadLine();
224+
}
225+
}
226+
}
227+
```
228+
229+
## Step 5: Delete data
230+
231+
Use the following code to connect and delete data using a DELETE SQL statement.
232+
233+
```csharp
234+
using System;
235+
using Npgsql;
236+
namespace Driver
237+
{
238+
public class AzurePostgresDelete
239+
{
240+
241+
static void Main(string[] args)
242+
{
243+
// Replace below argument with connection string from portal.
244+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
245+
246+
connStr.TrustServerCertificate = true;
247+
248+
using (var conn = new NpgsqlConnection(connStr.ToString()))
249+
{
250+
251+
Console.Out.WriteLine("Opening connection");
252+
conn.Open();
253+
using (var command = new NpgsqlCommand("DELETE FROM pharmacy WHERE pharmacy_id = @n", conn))
254+
{
255+
command.Parameters.AddWithValue("n", 0);
256+
int nRows = command.ExecuteNonQuery();
257+
Console.Out.WriteLine(String.Format("Number of rows deleted={0}", nRows));
258+
}
259+
}
260+
Console.WriteLine("Press RETURN to exit");
261+
Console.ReadLine();
262+
}
263+
}
264+
}
265+
```
266+
267+
## COPY command for super fast ingestion
268+
269+
The COPY command can yield [tremendous throughput](https://www.citusdata.com/blog/2016/06/15/copy-postgresql-distributed-tables) while ingesting data into Hyperscale (Citus). The COPY command can ingest data in files, or from micro-batches of data in memory for real-time ingestion.
270+
271+
### COPY command to load data from a file
272+
273+
The following code is an example for copying data from a CSV file to a database table.
274+
275+
It requires the file [pharmacies.csv](https://download.microsoft.com/download/d/8/d/d8d5673e-7cbf-4e13-b3e9-047b05fc1d46/pharmacies.csv).
276+
277+
```csharp
278+
using Npgsql;
279+
public class csvtotable
280+
{
281+
282+
static void Main(string[] args)
283+
{
284+
String sDestinationSchemaAndTableName = "pharmacy";
285+
String sFromFilePath = "C:\\Users\\Documents\\pharmacies.csv";
286+
287+
// Replace below argument with connection string from portal.
288+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
289+
290+
connStr.TrustServerCertificate = true;
291+
292+
NpgsqlConnection conn = new NpgsqlConnection(connStr.ToString());
293+
NpgsqlCommand cmd = new NpgsqlCommand();
294+
295+
conn.Open();
296+
297+
if (File.Exists(sFromFilePath))
298+
{
299+
using (var writer = conn.BeginTextImport("COPY " + sDestinationSchemaAndTableName + " FROM STDIN WITH(FORMAT CSV, HEADER true,NULL ''); "))
300+
{
301+
foreach (String sLine in File.ReadAllLines(sFromFilePath))
302+
{
303+
writer.WriteLine(sLine);
304+
}
305+
}
306+
Console.WriteLine("csv file data copied sucessfully");
307+
}
308+
}
309+
}
310+
```
311+
312+
### COPY command to load data in-memory
313+
314+
The following code is an example for copying in-memory data to table.
315+
316+
```csharp
317+
using Npgsql;
318+
using NpgsqlTypes;
319+
namespace Driver
320+
{
321+
public class InMemory
322+
{
323+
324+
static async Task Main(string[] args)
325+
{
326+
327+
// Replace below argument with connection string from portal.
328+
var connStr = new NpgsqlConnectionStringBuilder("Server = <host>; Database = citus; Port = 5432; User Id = citus; Password = {your password}; Ssl Mode = Require;");
329+
330+
connStr.TrustServerCertificate = true;
331+
332+
using (var conn = new NpgsqlConnection(connStr.ToString()))
333+
{
334+
conn.Open();
335+
var text = new dynamic[] { 0, "Target", "Sunnyvale", "California", 94001 };
336+
using (var writer = conn.BeginBinaryImport("COPY pharmacy FROM STDIN (FORMAT BINARY)"))
337+
{
338+
writer.StartRow();
339+
foreach (var item in text)
340+
{
341+
writer.Write(item);
342+
}
343+
writer.Complete();
344+
}
345+
Console.WriteLine("in-memory data copied sucessfully");
346+
}
347+
}
348+
}
349+
}
350+
```
351+
352+
## Next steps
353+
354+
Learn to [build scalable applications](howto-build-scalable-apps-overview.md)
355+
with Hyperscale (Citus).

0 commit comments

Comments
 (0)