A newer version of this documentation is available.

View Latest

Managing Connections Using the .NET SDK with Couchbase Server

This section describes how to connect the .NET SDK to a Couchbase cluster and bucket. It contains best practices as well as information on the connection string, SSL and other advanced connection options.

Connecting to a Cluster and Opening a Bucket

Connecting to a bucket is a two-step process: first, a Cluster object needs to be created or the ClusterHelper object needs to be initialized, followed by one or more calls to OpenBucket() or GetBucket(..):

var cluster = Cluster();
var credentials = new PasswordAuthenticator("Administrator", "password");
cluster.Authenticate(credentials);
var bucket = cluster.OpenBucket("default");

//or alternately
ClusterHelper.Initialize(new ClientConfiguration(), credentials);
var bucket = ClusterHelper.GetBucket("default");
The ClusterHelper is a singleton/multiton that makes it easier to manage resources and instances in server runtime environments such as ASP.NET and Owin/Katana. A ClusterHelper will make a singleton instance of a Cluster object and configuration and store references to opened IBucket objects that can be reused throughout the lifespan of an application.
The PasswordAuthenticator is used for connecting to Couchbase Server 5.0 and greater using RBAC (Role Based Access Control). In this case we are using the administrator account, however, a more secure way to connect is to create a user with minimal privileges and a unique password. If you are connecting to an older server version that does not use RBAC then you would omit the PasswordAuthenticator and instead pass the bucket password into the OpenBucket method.

If no further arguments are applied, this code connects to localhost and opens the default bucket. While this is suitable for development, you most probably want to connect to a remote cluster and also a different bucket. To do this, you create a ClientConfiguration object with a custom configuration:

//define a configuration object
var config = new ClientConfiguration {
   Servers = new List<Uri> {
       new Uri("http://192.168.56.101:8091"),
       new Uri("http://192.168.56.102:8091")
   }
};

//create the cluster and pass in the RBAC user
var cluster = new Cluster(config);
var credentials = new PasswordAuthenticator("Administrator", "password");
cluster.Authenticate(credentials);

//open the new bucket
var bucket = cluster.OpenBucket("mybucket");

//or alternately
ClusterHelper.Initialize(config, credentials);
var bucket = ClusterHelper.GetBucket("mybucket");

The ClientConfiguration object also exposes per bucket configuration settings, for example:

var config = new ClientConfiguration{
    Servers = new List<Uri> {
        new Uri("http://192.168.56.101:8091"),
        new Uri("http://192.168.56.102:8091")
    },
    BucketConfigs = new Dictionary<string, BucketConfiguration> {{
            "mybucket", new BucketConfiguration{
                BucketName = "mybucket"
            }
        }
     }
  };
//create the authenticator for passing in the user and password for RBAC
var credentials = new PasswordAuthenticator("Administrator", "password");

//create the cluster and open the new bucket
var cluster = new Cluster(config, credentials);
var bucket = cluster.OpenBucket("mybucket");

//or alternately
ClusterHelper.Initialize(config, credentials);
var bucket = ClusterHelper.GetBucket("mybucket");

It is very important in a production setup to pass in at least two or three nodes of the cluster because if the first one in the list fails the other ones can be tried. After initial contact is made, the bootstrap list provided by the user is thrown away and replaced with a list provided by the server (which contains all nodes of the cluster).

As an alternative to programmatic configuration, the SDK also supports configuration via config file and soon will support JSON config files. Here is an example of an App.Config that is equivalent to the configuration above and assumes that you are connecting to Couchbase Server 5.0 or greater using RBAC:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <sectionGroup name="couchbaseClients">
      <section name="couchbase" type="Couchbase.Configuration.Client.Providers.CouchbaseClientSection, Couchbase.NetClient" />
    </sectionGroup>
  </configSections>
  <couchbaseClients>
    <couchbase username="Administrator" password="password">
      <servers>
        <add uri="http://192.168.56.101:8091"></add>
        <add uri="http://192.168.56.102:8091"></add>
      </servers>
      <buckets>
        <add name="mybucket" password="mybucketpassword"></add>
      </buckets>
    </couchbase>
  </couchbaseClients>
</configuration>

To open these buckets you would pass the path to the configuration section:

var cluster = new Cluster("couchbaseClients/couchbase");
var bucket = cluster.OpenBucket("mybucket");

//or alternatively
ClusterHelper.Initialize("couchbaseClients/couchbase");
var bucket = cluster.OpenBucket("mybucket");

More buckets can be open at the same time if needed:

var bucket1 = cluster.OpenBucket("bucket1");
var bucket2 = cluster.OpenBucket("bucket2");

If more than one bucket is open at a time, the underlying internals of the client makes sure to utilize the resources as best as possible, that is sharing sockets, thread pools and so on.

Here are some very important things to keep in mind:

  • Always create only one instance of a Cluster and share it across threads (same with buckets) or use the ClusterHelper to help you do this. The ClusterHelper is a singleton for a Cluster instance and a "multi-ton" for bucket instances; the buckets will be cached and reused.

  • The SDK is thread-safe, so no additional synchronization is needed when interacting with the SDK.

  • If different clusters need to be accessed, you can do this with multiple Cluster instances.

  • The Cluster instance and the ClusterHelper class should be initialized when the application starts up and closed via Dispose() when the application shuts down.

Disconnecting from a Bucket

The most common case is to Dispose the whole Cluster from the server, which has the same effect as closing all buckets manually and in addition close all underlying resources like threads and sockets. This also means that once Dispose() has been called, you can’t reopen buckets from the same Cluster instance.

cluster.Dispose();

After a Dispose() called on a Cluster instance any subsequent attempts to open or use a bucket or cluster will cause a ObjectDisposedException to be thrown. You can also Dispose of a bucket instance:

bucket.Dispose();

This will release only the resources allocated for this bucket and it is possible to reopen it at a later point.

If you do not Dispose of the Cluster or bucket instance that you are using in your application, eventually the AppDomain or process will destroy the objects however, any underlying resources (sockets for example) will be closed by the OS whenever it decides to do so. This can lead to other problems so always Dispose of your Cluster and bucket objects before the hosting application shuts down.

Connecting with SSL

Couchbase Server EE 3.0 and later supports full encryption of client-side traffic. That includes key-value type operations, queries, and configuration communication. Make sure to have a proper Couchbase Server version installed before proceeding with configuring encryption on the client side.

To configure encryption for the .NET SDK:

  1. Copy and import the certificate from the cluster into your certificate store

  2. Enable encryption on the client by setting ClientConfiguration.UseSsl to true

Depending upon your version of Windows and whether or not you are using OWIN or IIS, how you import into your certificate store may vary.

If you are running on localhost and just want to enable it for a development machine, just copying and pasting it suffices. Navigate in the admin UI to Settings  Cluster and copy the input box of the SSL certificate into a file on your machine (here named cluster.crt). It looks similar to this:

-----BEGIN CERTIFICATE-----
MIICmDCCAYKgAwIBAgIIE4FSjsc3nyIwCwYJKoZIhvcNAQEFMAwxCjAIBgNVBAMT
ASowHhcNMTMwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjAMMQowCAYDVQQDEwEq
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzz2I3Gi1XcOCNRVYwY5R
................................................................
mgDnQI8nw2arBRoseLpF6WNw22CawxHVOlMceQaGOW9gqKNBN948EvJJ55Dhl7qG
BQp8sR0J6BsSc86jItQtK9eQWRg62+/XsgVCmDjrB5owHPz+vZPYhsMWixVhLjPJ
mkzeUUj/kschgQ0BWT+N+pyKAFFafjwFYtD0e5NwFUUBfsOyQtYV9xu3fw+T2N8S
itfGtmmlEfaplVGzGPaG0Eyr53g5g2BgQbi5l5Tt2awqhd22WOVbCalABd9t2IoI
F4+FjEqAEIr1mQepDaNM0gEfVcgd2SzGhC3yhYFBAH//8W4DUot5ciEhoBs=
-----END CERTIFICATE-----

Paste this into notepad running with administrative privileges and then save it to disk with a file extension of .crt and a file type of "All Files". Then right click on the file and select "Import Certificate", then select "Local Machine", select the "Trusted Root Certificate Authorities" and finally "Finish". Once you have done this, all traffic between the client and the server will be encrypted.

Using DNS SRV records

As an alternative to specifying multiple hosts in your program, you can get the actual bootstrap node list from a DNS SRV record. The following steps are necessary to make it work:

  1. Set up your DNS server to respond properly from a DNS SRV request.

  2. Enable it on the SDK and point it towards the DNS SRV entry.

Your DNS server should be set up like this (one row for each bootstrap node):

_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node1.example.com.
_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node2.example.com.
_couchbase._tcp.example.com.  3600  IN  SRV  0  0  0  node3.example.com.
The ordering, priorities, ports and weighting are completely ignored and should not be set on the records to avoid ambiguities.

If you plan to use secure connections, you use _couchbases instead:

_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node1.example.com.
_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node2.example.com.
_couchbases._tcp.example.com.  3600  IN  SRV  0  0  0  node3.example.com.

DNS SRV bootstrapping is available in the .NET SDK from version 2.3.9. In order to make the SDK use the SRV records, you need to create a custom implemention of IServerResolver and then use the custom class name in the Couchbase client configuration. Below is an example web.config that uses a custom resolver implementation.

<couchbase>
  <buckets>
    <add name="default" />
  </buckets>
  <serverResolver type="MyApp.MyServerResolver, MyApp" />
</couchbase>

The .NET Framework does not offer DNS-SRV resolution directly but there are some third party packages that can help do that such as DnsClient. Also, if you’re creating an ASP.NET Core web application, there is the Couchbase.Extensions.DnsDiscovery community package that can resolve and setup the configuration for you.