Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Full Stack Development with .NET and NoSQL - Chicago, September 2016

Full Stack Development with .NET and NoSQL - Chicago, September 2016

Application development and data storage needs are changing constantly. Today you might find yourself using ASP.NET MVC, but tomorrow you might need to use ASP.NET Core. Maybe tomorrow you find yourself needing to store a more diverse set of data than you did yesterday, creating a challenging data upgrade path. What if you suddenly decide that you need to include a mobile application as well as a web application? How do you prepare your enterprise to be able to accommodate these various technology shifts as the years pass?

In this session we will talk about what is different about this generation of web applications and how a solid development approach must consider the latency, throughput and interactivity demand by users across both mobile devices, web browsers, and IoT. We'll see how to include a NoSQL database in such applications to support a flexible data model and easy scalability required for modern development.

We will see how to create a full stack application that makes use of .NET, Couchbase NoSQL, and AngularJS, but can very easily be altered to meet the needs of your organization should things change in the future.

Speakers
Matthew D. Groves is a guy who loves to code. It doesn't matter if it's "enterprisey" C# apps, cool jQuery stuff, contributing to OSS, or rolling up his sleeves to dig into some PHP. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works from home for Heuristic Solutions, and loves spending time with his wife and 2 kids, watching the Cincinnati Reds, and getting involved in the developer community. He is the author of AOP in .NET: Practical Aspect-Oriented Programming.

Jason Farrell is a Senior Technical Consultant at West Monroe Partners. You can find Jason blogging at www.jfarrell.net and on Twitter at @jfarrell

Matthew D. Groves

September 08, 2016
Tweet

More Decks by Matthew D. Groves

Other Decks in Technology

Transcript

  1. ©2016 Couchbase Inc. 2 Where am I? • Chicago .NET

    Developer’s Group • http://www.meetup.com/chicagodevnet/
  2. ©2016 Couchbase Inc. 3 Before we begin though  Claire

    Woo Cho  My girlfriend of 3yrs  She attends many of our user groups  Recently became a Nurse at Northwestern
  3. ©2016 Couchbase Inc. 8 Who am I? • Matthew D.

    Groves • Developer Advocate for Couchbase • @mgroves on Twitter • Podcast and blog: http://crosscuttingconcerns.com • BS, MBA, Microsoft MVP • “I am not an expert, but I am an enthusiast.” – Alan Stevens
  4. ©2016 Couchbase Inc. 10 Tweet something, get a sticker! Use

    #Couchbase Tweet something interesting you’ve learned. Tweet a picture. I’ve got stickers!
  5. The Part of the Stack With Software Application Development and

    Infrastructure Management with .NET and Second Generation Non-Relational Document Databases Which by the Way Actually Do Have a SQL-like Query Language
  6. ©2016 Couchbase Inc. 14 Application Stacks L A M P

    M E A N • OS • Web Server • Framework • DB • Language
  7. ©2016 Couchbase Inc. 16 Where is NoSQL a Good Fit?

    Low-latency Critical High Throughput or Large Numbers of Users Unknown Demand with Sudden growth Predominantly Direct Document Access Read / Mixed / Write-heavy Workloads Traditional Business Applications Transaction-heavy Apps Legacy Hardware Full ACID support Web / Mobile / IoT Legacy Business Apps
  8. ©2016 Couchbase Inc. 17 What is Couchbase? Couchbase is a

    distributed operational database that enables you to develop with agility and operate at any scale. Managed Cache Key-Value Store Document Database Embedded Database Sync Management
  9. ©2016 Couchbase Inc. 18 Agility Easier, Faster Development Flexible Data

    Modeling Powerful Querying SQL Integration & Migration Big Data Integration Mobile / IoT
  10. ©2016 Couchbase Inc. 19 Scale Elastic Scalability Consistent High Performance

    Always-on Availability Multi-Data Center Deployment Simple, Powerful Administration Enterprise Grade Security
  11. ©2016 Couchbase Inc. 28 The Couchbase .NET SDK  Available

    on NuGet (CouchbaseNetClient)  Compatible with full .NET Framework  .NET Core coming soon
  12. ©2016 Couchbase Inc. 29 Building Applications with .NET SDK //include

    the namespaces using Couchbase; using Couchbase.Core using Couchbase.N1QL;
  13. ©2016 Couchbase Inc. 30 Building Applications with .NET SDK //connecting

    to a Couchbase cluster var config = new ClientConfiguration(); config.Services = new List<Uri> { “couchbase://localhost” }; ClusterHelper.Initialize(config); //opening a bucket in the cluster _bucket = ClusterHelper.GetBucket("travel-sample", “password"); //preparing N1ql var myQuery = QueryRequest.Create(“SELECT * FROM `travel-sample`“); //creating and saving a Document var document = new Document<dynamic> { Id = “my-key", Content = new { firstname = “Matt", lastname = “Groves" } }; _bucket.Insert(document);
  14. ©2016 Couchbase Inc. 31 .NET public async Task<dynamic> Query(string n1ql)

    { var queryToRun = QueryRequest.Create(n1ql); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  15. ©2016 Couchbase Inc. 32 .NET public async Task<dynamic> Query(string n1ql)

    { var queryToRun = QueryRequest.Create(n1ql); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  16. ©2016 Couchbase Inc. 33 .NET public async Task<dynamic> Query(string n1ql)

    { var queryToRun = QueryRequest.Create(n1ql); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  17. ©2016 Couchbase Inc. 34 .NET public async Task<dynamic> Query(string n1ql)

    { var queryToRun = QueryRequest.Create(n1ql); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  18. ©2016 Couchbase Inc. 35 .NET public async Task<dynamic> Query(string n1ql)

    { var queryToRun = QueryRequest.Create(n1ql); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  19. ©2016 Couchbase Inc. 41 ASP.NET Configuration // Web.config <appSettings> …

    <add key="CouchbaseServer" value="couchbase://127.0.0.1:8091" /> <add key="CouchbaseBucket" value="restful-sample" /> … </appSettings>
  20. ©2016 Couchbase Inc. 42 ASP.NET Configuration // Global.asax.cs protected void

    Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); var config = new ClientConfiguration(); config.Servers = new List<Uri> { new Uri(ConfigurationManager.AppSettings["CouchbaseServer"]) }; config.UseSsl = false; ClusterHelper.Initialize(config); }
  21. ©2016 Couchbase Inc. 44 WebAPI Controller // RestfulController.cs public class

    RestfulController : ApiController { readonly RecordModel _model; public RestfulController() { _model = new RecordModel(); } … }
  22. ©2016 Couchbase Inc. 45 WebAPI Create or Update Endpoint [Route("api/save")]

    [HttpPost] public async Task<IHttpActionResult> Save(Person body) { // validation if (string.IsNullOrEmpty(body.FirstName)) return BadRequest("A firstname is required"); if (string.IsNullOrEmpty(body.LastName)) return BadRequest("A lastname is required"); if (string.IsNullOrEmpty(body.Email)) return BadRequest("An email is required"); return Ok(await _model.Save(body)); }
  23. ©2016 Couchbase Inc. 46 WebAPI Get Document Endpoint [Route("api/get")] public

    async Task<IHttpActionResult> Get(Guid? document_id) { if (!document_id.HasValue) return BadRequest("A document id is required"); return Ok(await _model.GetByDocumentId(document_id.Value)); }
  24. ©2016 Couchbase Inc. 47 WebAPI Delete Endpoint [Route("api/delete")] [HttpPost] public

    async Task<IHttpActionResult> Delete(Person body) { if (!body.Document_Id.HasValue) return BadRequest("A document id is required"); return Ok(await _model.Delete(body.Document_Id.Value)); }
  25. ©2016 Couchbase Inc. 48 C# Upsert Document Function // RecordModel.cs

    public Task<IDocumentResult<dynamic>> Save(Person data) { var document = new Document<dynamic> { Id = data.Document_Id?.ToString() ?? Guid.NewGuid().ToString(), Content = new { firstname = data.FirstName, lastname = data.LastName, email = data.Email, type = "User" } }; return _bucket.UpsertAsync(document); }
  26. ©2016 Couchbase Inc. 50 C# Get Document with N1QL Function

    // RecordModel.cs public async Task<dynamic> GetByDocumentId(Guid documentId) { var n1ql = "SELECT firstname, lastname, email " + "FROM `" + bucketname + "` AS users " + "WHERE META(users).id = $1"; IQueryRequest query = QueryRequest.Create(n1ql); query.AddPositionalParameter(documentId); var r = await _bucket.QueryAsync<dynamic>(query); return r.Rows; }
  27. ©2016 Couchbase Inc. 51 C# Delete Document Function // RecordModel.cs

    public Task<IOperationResult> Delete(Guid documentId) => _bucket.RemoveAsync(documentId.ToString());
  28. ©2016 Couchbase Inc. 52 C# Delete Document Function // RecordModel.cs

    public Task<IOperationResult> Delete(Guid documentId) { return _bucket.RemoveAsync(documentId.ToString()); }
  29. ©2016 Couchbase Inc. 54 Get all documents // AngularJS app.js

    $scope.fetchAll = function() { $http( { method: "GET", url: "/api/getAll" } ) .success(function(result) { for(var i = 0; i < result.length; i++) { $scope.items[result[i].id] = result[i]; } }); }
  30. ©2016 Couchbase Inc. 55 Save a document // AngularJS app.js

    $scope.save = function(firstname, lastname, email) { $http( { method: "POST", url: "/api/save", data: { firstname: firstname, lastname: lastname, email: email, document_id: $stateParams.documentId } } ) }
  31. ©2016 Couchbase Inc. 57 C# Travel Sample public async Task<dynamic>

    FindAllRoutes(string from, string to) { var statement = @"SELECT faa, geo FROM `travel-sample` r WHERE airportname = $1 UNION SELECT faa, geo FROM `travel-sample` r WHERE airportname = $2"; var queryToRun = QueryRequest.Create(statement); queryToRun.AddPositionalParameter(from); queryToRun.AddPositionalParameter(to); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  32. ©2016 Couchbase Inc. 60 C# Travel Sample public async Task<dynamic>

    FindAllRoutesOnDay(string queryFrom, string queryTo, int leave) { var statement = @"SELECT r.id, a.name, s.flight, s.utc, r.sourceairport, r.destinationairport, r.equipment FROM `travel-sample` r UNNEST r.schedule s JOIN `travel-sample` a ON KEYS r.airlineid WHERE r.sourceairport = $1 AND r.destinationairport = $2 AND s.day = $3 ORDER BY a.name"; var queryToRun = QueryRequest.Create(statement); queryToRun.AddPositionalParameter(queryFrom); queryToRun.AddPositionalParameter(queryTo); queryToRun.AddPositionalParameter(leave); var results = await _bucket.QueryAsync<dynamic>(queryToRun); return results.Rows; }
  33. ©2016 Couchbase Inc. 64 Linq2Couchbase Model [DocumentTypeFilter("airline")] public class Airline

    { [JsonIgnore] public string Id { get; set; } [JsonProperty("type")] public string Type { get; set; } [JsonProperty("name")] public string Name { get; set; } public string Iata { get; set; } public string Icao { get; set; } public string Callsign { get; set; } public string Country { get; set; } }
  34. ©2016 Couchbase Inc. 65 Linq Queries var query = from

    x in bucket.Query<Airline>() where x.Type == "airline" select x.Name;
  35. ©2016 Couchbase Inc. 67 Couchbase Lite Embedded NoSQL Database Sync

    Gateway Secure Synchronization Couchbase Server Cloud NoSQL Database Couchbase Mobile
  36. ©2015 Couchbase Inc. 72 var db = Manager.SharedInstance.GetDatabase("mgroves-database"); var doc

    = db.CreateDocument(); doc.PutProperties(new Dictionary<string, object> { { "firstname", "Matt" }, { "lastname", "Groves" }, { "address", new { City = "Grove City", State = "OH", Country = "USA" } }, { "twitter", "https://twitter.com/mgroves" } });
  37. ©2016 Couchbase Inc. 73 Map Reduce Indexes • Building indexes

    in your native language • Results are persisted for fast querying • Just set breakpoints to debug
  38. ©2015 Couchbase Inc. 74 // create view var view =

    db.GetView("people"); view.SetMap((doc, emit) => { if(doc.ContainsKey("twitter")) emit(doc["_id"], doc); }, "1"); // execute the view var rows = db.GetExistingView("people") .CreateQuery() .Run(); foreach (var row in rows) { // print row.Document }
  39. ©2016 Couchbase Inc. 75 Change Notifications Change notifications • Listen

    for changes • Cuts down on a ton of cruft code • Data, queries, replications – even documents
  40. ©2015 Couchbase Inc. 76 db.Changed += Db_Changed; private void Db_Changed(object

    sender, DatabaseChangeEventArgs e) { foreach (var change in e.Changes) { if (change.IsConflict) { var docId = change.DocumentId; // log the document ID } } }
  41. ©2016 Couchbase Inc. 77 Sync Sync • Full multi-master replication

    • Ability to minimize battery drain • Change notifications and conflict detection
  42. ©2015 Couchbase Inc. 78 var push = db.CreatePushReplication("http://syncgateway"); var pull

    = db.CreatePullReplication("http://syncgateway"); push.Continuous = true; pull.Continuous = true; push.Start(); pull.Start();
  43. ©2016 Couchbase Inc. 83 Couchbase Days Join us for Couchbase

    Day on September 22 in Schaumburg, Illinois. This FREE day-long educational event will feature a combination of hands-on workshops and presentations on Couchbase Server.  Hyatt Place Chicago Schaumburg  September 22nd, 8:30a – 4p  http://www.couchbase.com/nosql- resources/events/2016/september/couchbase-day-schaumburg  http://info.couchbase.com/Couchbase_Day_Schaumburg_Register_web.html  http://tinyurl.com/cbdaychicago
  44. ©2016 Couchbase Inc. 84 Where do you find us? •

    developer.couchbase.com • blog.couchbase.com • @couchbasedev or @couchbase or #couchbase or @mgroves • forums.couchbase.com • stackoverflow.com/questions/tagged/couchbase