building .net apps using couchbase lite
DESCRIPTION
Learn how to develop with Couchbase Lite for .NET. The session will include a look at the development environment and required C# APIs using a walkthrough of a demo app.TRANSCRIPT
4
Couchbase LiteOn-device, lightweight, native
embedded JSON database
Sync GatewaySynchronize on-device
Couchbase Lite with Couchbase Server in the cloud
Couchbase ServerHigh performance, scalable, always-on JSON database in
the cloud
Couchbase Mobile
7
Pluggable Authentication
JavaScript sync function runs on all mutations.
Data Partitioning– channel(…): Routes the document to the named channel
Data Access Control– Read
– access(…): Grants access to a channel to a specified user, list of users, or a role
– role(…): Grants a user a role
– Write
– throw(…): Prevents a document mutation from persisting
– requireUser/Role/Access(…): Validates the user, their role assignments, or their access privileges.
Authentication, Partitioning, Access Control
Document Database Overview
• Semi-structured• Key-value pairs• Schemaless• JSON-backed• Very low-friction
Map Reduce Queries Overview
• Functional queries, instead of set-theoretic• Write query logic in pure C#, not SQL• Can be one-off, or auto-updating as data
changes• You probably already know how to use it:–Map is like LINQ’s Select method– Reduce is like LINQ’s Aggregate method
Sync Overview
• Master-master replication• Uses HTTP + REST• Offline mode for free• Manual or continuous modes• Automatic retry on failure• Responds to network changes
Programming Model
• You: make your changes to docs• Queries: will reflect those changes• Replicators: sync changes for you
Opening a Database
var db = Manager.SharedInstance.GetDatabase("foo");Debug.Assert(db != null);
var db = Manager.SharedInstance.GetExistingDatabase("foo");Debug.Assert(db == null);
Getting a Document
var doc = db.GetDocument("foo-doc");Debug.Assert(doc != null);
var doc = db.GetExistingDocument("foo-doc");Debug.Assert(doc == null);
Updating a New Document
var rev = doc.CreateRevision();var props = new Dictionary<string, object> { { "foo", "bar"}, { "fizz", "buzz"} };rev.SetUserProperties(props);rev.Save();
Updating an Existing Document
var props = doc.Properties;var newProps = new Dictionary<string, object>(props) { { "foo", "bar"} };doc.PutProperties(newProps); // Saves a new revision
Dealing with Changes
doc.Change += (sender, e) => { // e.g. if we get a conflict... if (e.Change.IsConflict) { // we can resolve it! }};
DocumentChange Members
StringBooleanBoolean
StringUri
RevisionInternal
DocumentId IsConflict IsCurrentRevision RevisionId SourceUrl WinningRevision
Handling Conflicts
var current = doc.CurrentRevision;foreach(var rev in doc.ConflictingRevisions){ var newRev = rev.CreateRevision(); if (rev.Equals(current)) { newRev.SetProperties(mergedProps); } else { newRev.IsDeletion = true; } newRev.Save();}
Auto-merging Properties using LINQ
Dictionary<string, object> mergedProps;try{ mergedProps = doc.ConflictingRevisions .SelectMany(rev => rev.UserProperties) .Distinct() .ToDictionary( kvp => kvp.Key, kvp => kvp.Value );} catch (ArgumentException ex) { // Merge conflict requires manual resolution.}
Create a View
var view = db.GetView("foo");Debug.Assert(view != null);
var view = db.GetExistingView("foo");Debug.Assert(view == null);
Add a Map Function
view.SetMap((doc, emit) => { var foo = (String)doc["foo"]; if (foo.Equals("bar")) { emit ("text", doc["text"]); }}, "1");
Using a Reduce Function
ReduceDelegate reducer = (keys, values, rereduce) => { var i = 0; var wordCount = 0; foreach(var key in keys) { if (key == "text") { var str = (String)values[i]; wordCount += str.Split(' ').Length; } } return wordCount;};view.SetMapReduce(mapper, reducer, "1");
Create a Query
var query = view.CreateQuery();
// Options, like...query.Completed += (sender, e) => { Log("Results: {0}", e.Rows);};query.Descending = true;
// Get records...var rows = await query.RunAsync();rows.Where(row => ...);
Create a LiveQuery
var liveQuery = query.ToLiveQuery();
// Respond to changes in the view.liveQuery.Changed += (sender, e) =>{ Log("Updates: {0}", e.Rows.Count);};
Pull Replicator
var uri = new Uri(syncGatewayUrl);var pull = db.CreatePullReplication(uri);pull.Continuous = true;pull.Changed += ReplicationChanged;pull.Start();
Push Replicator
var uri = new Uri(syncGatewayUrl);var push = db.CreatePushReplication(uri);push.Continuous = true;push.Changed += ReplicationChanged;push.Start();