C# Driver for Cassandra 2.5.1 Released
The new version of the C# Driver for Apache Cassandra is now available with support for manual paging and a friendlier routing API. On the Mapper and Linq components, it adds support for lightweight transactions.
Manual paging
When performing SELECT queries with large result sets, the driver automatically fetches a limited amount of rows by default retrieving the rows block by block as you iterate through the RowSet, to avoid having large amount of rows in memory.
Now it is possible to retrieve the next page based on the previous state, enabling you to store it and use it to fetch the following page in the future. This is useful for common scenarios like web pagers.
//prepare your queries once, as always var ps = session.Prepare("SELECT * from tbl1 WHERE key = ?"); // Disable automatic paging. var statement = ps .Bind(key) .SetAutoPage(false) .SetPageSize(pageSize); var rs = session.Execute(statement); // Store the paging state var pagingState = rs.PagingState; // Later in time ... // Retrieve the following page of results. var statement2 = ps .Bind(key) .SetAutoPage(false) .SetPagingState(pagingState) var rs2 = Session.Execute(statement2);
The PagingState
property of the RowSet
is not encrypted and can be used to inject values to retrieve other partitions, so be careful not to expose it to the end user.
If you want to manually page using the Linq or the Mapper, you can use Linq's ExecutePaged()
method, Mapper's FetchPage()
, or their async counterparts.
Routing queries
When using the TokenAwarePolicy load balancing policy, the driver uses the RoutingKey to determine which nodes is used as coordinator for a given statement. Due to the endianness difference between .NET / Mono (based on target CPU architecture) and the Cassandra protocol, it used to be difficult to specify a routing key.
Now, that we've made it easier to deal with routing keys, lets look at some basic examples with the different type of statements.
Prepared statements
When using prepared statements, the driver will determine which of the query parameters compose the partition key based on the prepared statement metadata and it will do all the routing for you. There is an special case when using named parameters where this won't be the case, check the documentation for more information.
Batch statements
If you want to choose which partition to target when using BatchStatement
, you must specify the values that compose the partition key.
//Consider a single uuid partition key var partitionKey = Guid.NewGuid(); var batch = new Batch(); // ... Add statements to the query batch.SetRoutingValues(partitionKey); session.Execute(batch);
Simple statements
If you plan to execute your query more than once, you should use prepared statements instead of SimpleStatement
. But if for some reason you want to define the routing key for a SimpleStatement
you can now use the SetRoutingValues()
//Consider a partition key composed by a uuid and a string var id = Guid.NewGuid(); var groupName = "A"; var query = new SimpleStatement(cql, id, groupName, value); // Specify the values that compose the partition key query.SetRoutingValues(id, groupName); session.Execute(query);
Lightweight transactions support on Linq and the Mapper
When using Lightweight transactions (LWT), it is generally required to check the result of the operation to see if the operation was applied and if not, check the field values that didn't match the condition. Now, it is possible to do that with Linq and the Mapper.
LWT with Linq
//Update the password only if a temporary token matches var info = users .Where(b => m.User == "User1") .Select(m => new User { Password = definitivePassword, Token = null }) .UpdateIf(m => m.Token == token) .Execute(); if (!info.Applied) { //It was not applied, you can check the existing value var userToken = info.Existing.Token; }
LWT with the Mapper
var info = mapper.InsertIfNotExists(user); if (!info.Applied) { //It was not inserted, there was an existing user with the same keys //You can check the existing user User existingUser = info.Existing; }
Wrapping Up
Version 2.5.1 of the C# driver is now available on Nuget, you can check all the tickets included in this release on Jira. Thanks to all who provided contributions and bug reports. The continued involvement of the community is appreciated, review or contribute source code on GitHub and join the project mailing list.