-
-
Notifications
You must be signed in to change notification settings - Fork 131
Extra C# Driver Features
In general, the C# driver and Java driver are both API compatible. The Java documentation can be followed easily without much trouble.
The C# driver, however, offers additional language syntax that goes beyond the original Java driver. The additional language features are highlighted here.
Java and C#
r.table("marvel").getAll("man_of_steel").optArg("index", "code_name")
.run(conn);
Additionally, the C# driver supports indexer operators which allows the use of anonymous type for optional arguments.
r.table("marvel").getAll("man_of_steel")[new {index="code_name"}]
.run(conn);
Java, Python, JavaScript and C#
r.table("marvel").get("12345")["field"]["subfield"] // Python
r.table("marvel").get("12345")("field")("subfield") // JavaScript
r.table("marvel").get("12345").getField("field").getField("subfield") //Java
r.table("marvel").get("12345").getField("field").getField("subfield") // C#
Additionally, the C# driver also supports .bracket() via indexer operator:
r.table("marvel").get("12345")["field"]["subfield"] // C#
The Python, JavaScript, and Java drivers all expect the developer to know the shape of a query result. The C# driver follows a similar paradigm. However, supplying additional generic type information can help the DLR to perform a cast into a specific type.
new Foobar {id = "a", Baz = 4, Qux = 4}
// DLR dynamic
/* var result is 4 of type dynamic */
var result = r.table("foobar").get("a")["Baz"].run(conn);
/* long result is 4 of type long */
long result = r.table("foobar").get("a")["Baz"].run(conn);
// Give the compiler and run-time more type information with run<T>()
/* int result is 4 of type int */
int result = r.table("foobar").get("a")["Baz"].run<int>(conn);
Notice the result declarations long and int and their respective run and run<T> calls. The underlying deserializer, Newtonsoft.Json determined the underlying type (without T) is a long. Given T as int, the deserializer can make a more specific deserialization of the result.
When the result of a query is a stream (ie: query → stream), be sure to declare that the expected result as a Cursor<T>. The following example below shows how to expect a cursor:
Cursor<int> result = r.range(1,4).run<int>();
Notice the DLR magic above, run<int> returns Cursor<int> not int. Since the server's response for the query above is a stream it is the responsibility of the driver to return a cursor. Also note, in the example above, run<T> T specifies the cursor item type.
There is a slight performance cost to run<T> since the execution context involves the DLR. As a best practice, queries that return a cursor should use .runCursor<T>(). .runCursor<T> bypasses the DLR and the execution context remains within the CLR type system to return a Cursor<T> just as any normal CLR method call.
Cursor<int> result = r.range(1,4).runCursor<int>(conn);
foreach(var i in result){
Console.WriteLine(i);
}
/* Output:
1
2
3
*/
This C# driver supports POCO serialization to RethinkDB via Newtonsoft.Json. The default serializer can be overridden by replacing the JsonSerializer in the Converter.Serializer static property.
RethinkDb.Driver.Net.Converter.Serializer = new JsonSerializer(/*custom*/);
Keep in mind, however, there are native types that RethinkDB expects in a specific JSON format. Native ReQL types like time, dates, binary data, and arrays (DateTime, DateTimeOffset, byte[], IEnumerable) need to be in a specific JSON format over-the-wire in order to perform ReQL operations on them. By default, native ReQL types are converted automatically if the default Converter.Serializer is used. More information about ReQL pseudo types can be found here.
Overriding the default Converter.Serializer requires including the pseudo type converters when replacing the default serializer in order to maintain correct type conversions between native types and ReQL pseudo types. Instances of the JSON converters can be found on static properties in the Converter class:
Converter.DateTimeConverterConverter.BinaryConverterConverter.GroupingConverterConverter.PocoArrayConverterConverter.PocoExprConverter
The following is only possible with C#
public class TopPlayer
{
public int PlayerId { get; set; }
}
var games = new[]
{
new Game {id = 2, player = "Bob", points = 15, type = "ranked"},
new Game {id = 5, player = "Alice", points = 7, type = "free"},
new Game {id = 11, player = "Bob", points = 10, type = "free"},
new Game {id = 12, player = "Alice", points = 2, type = "free"},
};
List<TopPlayer> result =
r.expr(games)
.filter(g => g["points"].gt(9))
.map(g => new { PlayerId = g["id"] })
// Anonymous Type Projection into TopPlayer
.run<List<TopPlayer>>(conn);
result.Dump();
result.ShouldBeEquivalentTo(new[]
{
new TopPlayer {PlayerId = 2},
new TopPlayer {PlayerId = 11}
});
The following is only possible with C#
//Objects inside Foobar table:
new Foobar {id = "a", Baz = 1, Qux = 1}
new Foobar {id = "b", Baz = 2, Qux = 2}
new Foobar {id = "c", Baz = 3, Qux = 3}
var exprA = r.table("foobar").get("a")["Baz"]; // 1
var exprB = r.table("foobar").get("b")["Qux"]; // 2
int result = (exprA + exprB + 1).run<int>(conn);
// Everything between (...) executes on the server
// and returns result 4.
The last line, (exprA + exprB + 1) is converted into an AST and sent to the server for evaluation including the + 1) part. The + 1) is not evaluated on the client. Here's what happens:
The compiler/run-time knows exprA is type ReqlExpr, moves right to exprB (also of type ReqlExpr), applies the + operator overload for adding two ReqlExprs who's sum is also ReqlExpr (under the hood, all we're doing is exprA.add(exprB)). Lastly, the evaluation moves right again to the last + 1) but encounters an int type. The implicit conversion operator kicks in (int -> ReqlExpr) and converts int into a Datum(1) (which inherits from ReqlExpr). Finally, the last + Datum(1) can be evaluated. The final equivalent ReQL sequence is: exprA.add(exprB).add(new Datum(1)). Beautiful. ❤️
Happy ReQL-ing! 🚀
- Home
- Query Examples
- Logging
- Connections & Pooling
- Extra C# Features
- GOTCHA Goblins!
- LINQ to ReQL Provider
- Differences
- Java ReQL API Documentation