Skip to content

Commit 8cda65d

Browse files
committed
Npgsql: Use improved .NET multi-line strings
Newer .NET/C# language versions borrow from Python for defining multi-line strings, using `"""`. This is much better for inlining JSON documents, because it doesn't need additional quoting.
1 parent 4c7b18b commit 8cda65d

File tree

2 files changed

+26
-25
lines changed

2 files changed

+26
-25
lines changed

by-language/csharp-npgsql/DemoTypes.cs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class AllTypesRecord
2626
public double? Double { get; set; }
2727
[JsonProperty("decimal")]
2828
public decimal? Decimal { get; set; }
29+
// TODO: Review the handling of the `BIT` type here.
2930
//[JsonProperty("bit")]
3031
//public BitArray Bit { get; set; }
3132
[JsonProperty("bool")]
@@ -66,7 +67,7 @@ public static async Task<DataTable> AllTypesExample(NpgsqlConnection conn)
6667
cmd.ExecuteNonQuery();
6768
}
6869

69-
await using (var cmd = new NpgsqlCommand(@"
70+
await using (var cmd = new NpgsqlCommand("""
7071
CREATE TABLE testdrive.example (
7172
-- Numeric types
7273
null_integer INT,
@@ -84,21 +85,21 @@ char CHARACTER(5),
8485
timestamp_notz TIMESTAMP WITHOUT TIME ZONE,
8586
ip IP,
8687
-- Container types
87-
""array"" ARRAY(STRING),
88-
""object"" OBJECT(DYNAMIC),
88+
"array" ARRAY(STRING),
89+
"object" OBJECT(DYNAMIC),
8990
-- Geospatial types
9091
geopoint GEO_POINT,
9192
geoshape GEO_SHAPE,
9293
-- Vector type
93-
""float_vector"" FLOAT_VECTOR(3)
94+
float_vector FLOAT_VECTOR(3)
9495
);
95-
", conn))
96+
""", conn))
9697
{
9798
cmd.ExecuteNonQuery();
9899
}
99100

100101
// Insert single data point.
101-
await using (var cmd = new NpgsqlCommand(@"
102+
await using (var cmd = new NpgsqlCommand("""
102103
INSERT INTO testdrive.example (
103104
null_integer,
104105
integer,
@@ -113,8 +114,8 @@ INSERT INTO testdrive.example (
113114
timestamp_tz,
114115
timestamp_notz,
115116
ip,
116-
""array"",
117-
""object"",
117+
"array",
118+
"object",
118119
geopoint,
119120
geoshape,
120121
float_vector
@@ -138,9 +139,8 @@ INSERT INTO testdrive.example (
138139
@geoshape,
139140
@float_vector
140141
);
141-
", conn))
142+
""", conn))
142143
{
143-
Console.WriteLine(cmd);
144144
cmd.Parameters.AddWithValue("null_integer", DBNull.Value);
145145
cmd.Parameters.AddWithValue("integer", 42);
146146
cmd.Parameters.AddWithValue("bigint", 42);
@@ -158,8 +158,9 @@ INSERT INTO testdrive.example (
158158
// FIXME: System.NotSupportedException: Cannot resolve 'hstore' to a fully qualified datatype name. The datatype was not found in the current database info.
159159
// https://github.com/crate/zk/issues/26
160160
// cmd.Parameters.AddWithValue("object", new Dictionary<string, string>(){{"foo", "bar"}});
161-
cmd.Parameters.AddWithValue("object", @"{""foo"": ""bar""}");
161+
cmd.Parameters.AddWithValue("object", """{"foo": "bar"}""");
162162
cmd.Parameters.AddWithValue("geopoint", new List<double>{85.43, 66.23});
163+
// TODO: Check if `GEO_SHAPE` types can be represented by real .NET or Npgsql data types.
163164
cmd.Parameters.AddWithValue("geoshape", "POLYGON ((5 5, 10 5, 10 10, 5 10, 5 5))");
164165
cmd.Parameters.AddWithValue("float_vector", new List<double> {1.1, 2.2, 3.3});
165166
cmd.ExecuteNonQuery();
@@ -194,34 +195,34 @@ public static async Task<DataTable> ContainerTypesExample(NpgsqlConnection conn)
194195
cmd.ExecuteNonQuery();
195196
}
196197

197-
await using (var cmd = new NpgsqlCommand(@"
198+
await using (var cmd = new NpgsqlCommand("""
198199
CREATE TABLE testdrive.container (
199200
-- Container types
200-
""array"" ARRAY(STRING),
201-
""object"" OBJECT(DYNAMIC)
201+
"array" ARRAY(STRING),
202+
"object" OBJECT(DYNAMIC)
202203
);
203-
", conn))
204+
""", conn))
204205
{
205206
cmd.ExecuteNonQuery();
206207
}
207208

208209
// Insert single data point.
209-
await using (var cmd = new NpgsqlCommand(@"
210+
await using (var cmd = new NpgsqlCommand("""
210211
INSERT INTO testdrive.container (
211-
""array"",
212-
""object""
212+
"array",
213+
"object"
213214
) VALUES (
214215
@array,
215216
@object
216217
);
217-
", conn))
218+
""", conn))
218219
{
219220
Console.WriteLine(cmd);
220221
// FIXME: While doing conversations with ARRAY types works natively,
221222
// it doesn't work for OBJECT types.
222223
// Yet, they can be submitted as STRING in JSON format.
223224
cmd.Parameters.AddWithValue("array", new List<string>{"foo", "bar"});
224-
cmd.Parameters.AddWithValue("object", @"{""foo"": ""bar""}");
225+
cmd.Parameters.AddWithValue("object", """{"foo": "bar"}""");
225226
cmd.ExecuteNonQuery();
226227
}
227228

by-language/csharp-npgsql/tests/DemoProgramTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,15 @@ public async Task TestAllTypesExample()
116116
// it doesn't work for OBJECT types.
117117
// Yet, they can be submitted as STRING in JSON format.
118118
Assert.Equal(new List<string>{"foo", "bar"}, row["array"]);
119-
Assert.Equal(@"{""foo"":""bar""}", row["object"]);
119+
Assert.Equal("""{"foo":"bar"}""", row["object"]);
120120

121121
// Geospatial types
122122
// TODO: Unlock native data types?
123123
// GEO_POINT and GEO_SHAPE types can be marshalled back and forth using STRING.
124124
// GEO_POINT is using a tuple format, GEO_SHAPE is using the GeoJSON format.
125125
// Assert.Equal(new List<double>{85.43, 66.23}, row["geopoint"]); // TODO
126126
Assert.Equal("(85.42999997735023,66.22999997343868)", row["geopoint"].ToString()); // FIXME
127-
Assert.Equal(@"{""coordinates"":[[[5.0,5.0],[5.0,10.0],[10.0,10.0],[10.0,5.0],[5.0,5.0]]],""type"":""Polygon""}", row["geoshape"]);
127+
Assert.Equal("""{"coordinates":[[[5.0,5.0],[5.0,10.0],[10.0,10.0],[10.0,5.0],[5.0,5.0]]],"type":"Polygon"}""", row["geoshape"]);
128128

129129
// Vector type
130130
Assert.Equal((new List<double>{1.1, 2.2, 3.3}).Select(d => (float) d).ToArray(), row["float_vector"]);
@@ -145,10 +145,10 @@ public async Task TestContainerTypesExample()
145145
// it doesn't work for OBJECT types.
146146
// Yet, they can be submitted as STRING in JSON format.
147147
Assert.Equal(new List<string>{"foo", "bar"}, row["array"]);
148-
Assert.Equal(@"{""foo"":""bar""}", row["object"]);
148+
Assert.Equal("""{"foo":"bar"}""", row["object"]);
149149

150150
// Run a special query indexing into ARRAY types.
151-
await using (var cmd = new NpgsqlCommand(@"SELECT ""array[2]"" AS foo FROM testdrive.container", conn))
151+
await using (var cmd = new NpgsqlCommand("""SELECT "array[2]" AS foo FROM testdrive.container""", conn))
152152
await using (var reader = cmd.ExecuteReader())
153153
{
154154
var dataTable = new DataTable();
@@ -157,7 +157,7 @@ public async Task TestContainerTypesExample()
157157
}
158158

159159
// Run a special query indexing into OBJECT types.
160-
await using (var cmd = new NpgsqlCommand(@"SELECT ""object['foo']"" AS foo FROM testdrive.container", conn))
160+
await using (var cmd = new NpgsqlCommand("""SELECT "object['foo']" AS foo FROM testdrive.container""", conn))
161161
await using (var reader = cmd.ExecuteReader())
162162
{
163163
var dataTable = new DataTable();

0 commit comments

Comments
 (0)