Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, April 20, 2015
( Spotify )

https://github.com/DanielLarsenNZ/Radiostr-SpotifyWebApi

Initial thoughts on his code

  • Tidy, and designed with lots of traditional comments
  • Async all the way (just use .Wait to make it sync)
  • Testable
    • HttpClient mocking out
  • ClientCredentialsAuthorizationApi
  • Caching
  • Defensive code checking for NullOrEmpty

Putting on a test Console App

image

Annoying that breakpoint is caught at top level.

image
Okay so I just need to break in VS!

| | # 
# Friday, April 17, 2015
( LSCC | Spotify )

Thanks to everyone who came last night - really appreciated the questions and laughter!!

http://www.meetup.com/london-software-craftsmanship/events/221749420/
https://skillsmatter.com/meetups/7134-software-craftsmanship-with-music-and-financial-trading

The soundtrack before the talk was:

image

An Elvis impersonator, covering dead people.  I really like this album
http://www.davestopmusic.com/Artists/Details/1W04ZWzAoPZ6eY754HgXQP

The Talk

www.davestopmusic.com  (main site – Amazon EC2)

dmusic.azurewebsites.net (test site - Azure)

https://ci.appveyor.com/project/djhmateer/davesmusic – Build / Test / Deploy to Azure

 

Code and presentation: https://github.com/djhmateer/davesmusic (I’ll put the HQ videos up there this weekend)

Music Discussed

Where to Next?

Got some great questions on testing which is making me think of where next..

| | # 
# Tuesday, April 14, 2015
( Spotify )

image

image
Doing anything that needs authorisation fails.

| | # 

Zach Holman inspired
Rob Conery inspired
Chris Michel
Amy Palamou

  • Large fonts
  • Simple colours
  • A few fonts
  • maybe Subtle imagery

‘Live coding’ better..
Record every demo? – Camtasia?

Fontawesome – then hot

http://www.fontsquirrel.com/fonts/list/hot

  • chunck5 – heading
  • montserrat
| | # 
# Monday, April 13, 2015

Win + (zoom in)

Win – (zoom out)

Win Esc (to exit)

| | # 
# Sunday, April 05, 2015
( Dapper | Miniprofiler | MVC5 )

Got working

using (profiler.Step("Doing complex stuff")) { using (profiler.Step("Step A")) { Thread.Sleep(5); } using (profiler.Step("Step B")) { Thread.Sleep(25); } }

Simple example of timing

using (mp.CustomTiming("http", url)) { var json = CallAPI(stopWatchResult, url); return json; }

This is good

image

Interesting – Azure DNS broken again, or just slow network?

image
A good use case for Async!

image
Well – actually I could increase the limit size from 20 to 50 to make it faster.

image
Yes as expected it makes it faster to do all gets in parallel.

image

image
Showing the difference

| | # 
( Dapper )

http://stackoverflow.com/questions/10030285/dapper-rainbow-vs-dapper-contrib

Dapper.Contrib

  • CRUD
  • Change tracking

Dapper.Rainbow

  • CRUD
  • Jan 12th 2012
  • 5k downloads

Dapper Extensions

  • CRUD
  • August 5th 2014
  • 37k downloads

Dapper.SimpleCRUD

  • Feb 27th, 2015
  • 5k

https://github.com/ericdc1/Dapper.SimpleCRUD/
https://github.com/ericdc1/Dapper.SimpleCRUD/wiki/T4-Template – generate POCOS from DB

Read

public Contact Get(int id){ return db.Get<Contact>(id); }

instead of:

public Contact Find(int id) { // Anonymous types for parameters // if not found, will return a null return db.Query<Contact>("SELECT * FROM Contacts WHERE Id = @Id", new { id }).SingleOrDefault(); }

 

had to mark up the class as:

// used for SimpleCRUD [Table("Contacts")] public class Contact { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public string Company { get; set; } public string Title { get; set; } //Additional properties not in database [Editable(false)] public bool IsNew { get { return this.Id == default(int); } } }

Read Many

public IEnumerable<Contact> GetList(){ return db.GetList<Contact>(); }

instead of:

public List<Contact> GetAll() { return db.Query<Contact>("SELECT * FROM Contacts").ToList(); }

Insert

Getting a strange error, so looking at the tests in source: https://github.com/ericdc1/Dapper.SimpleCRUD

image
Nice tests – uses reflection to find the tests

public Contact Insert(Contact contact) { using (var db = GetOpenConnection()){ var id = db.Insert(contact); contact.Id = (int)id; return contact; } }

so this works.. instead of:

public Contact InsertOld(Contact contact) { using (var db = GetOpenConnection()){ var sql = "INSERT INTO Contacts (FirstName, LastName, Email, Company, Title) VALUES(@FirstName, @LastName, @Email, @Company, @Title); " + "SELECT CAST(SCOPE_IDENTITY() as int)"; var id = db.Query<int>(sql, contact).Single(); contact.Id = id; return contact; } }

Makes life a bit easier.

Update and Delete

public Contact Update(Contact contact){ using (var db = GetOpenConnection()) { db.Update(contact); return contact; } } public void Delete(Contact contact) { using (var db = GetOpenConnection()) { db.Delete(contact); } }

instead of:

public Contact UpdateOld(Contact contact) { using (var db = GetOpenConnection()){ var sql = "UPDATE Contacts " + "SET FirstName = @FirstName, " + " LastName = @LastName, " + " Email = @Email, " + " Company = @Company, " + " Title = @Title " + "WHERE Id = @Id"; db.Execute(sql, contact); return contact; } } public void DeleteOld(int id) { using (var db = GetOpenConnection()){ db.Execute("DELETE FROM Contacts WHERE Id = @Id", new{id}); } }

So quite a bit simpler.  Next step is to see how it goes with more complexity, and to get some figures for perf and see the actual queries in the UI/Log files.

http://stackoverflow.com/questions/14318571/how-to-read-an-sql-query-generated-by-dapper

| | # 
# Friday, April 03, 2015
( Dapper )

What is a Micro ORM?

  • Lightweight (no designer or config files)
  • Fast
  • Simple (code focus, and some cases closer to the metal ie more SQL)
  • Good at mapping from POCO to DB parameters, and back

http://www.pluralsight.com/courses/exercise-files/dotnet-micro-orms-introduction

Dapper vs EF

static void Main(string[] args) { Console.Title = "Micro ORM Demo"; var connectionString = ConfigurationManager.ConnectionStrings["contactsDB"].ConnectionString; // EF //var context = new ContactsContext(connectionString); //var contacts = context.Contacts.ToList(); //var contacts = context.Contacts.Where(c => c.Id == 1); // Dapper - implemented using extension methods IDbConnection db = new SqlConnection(connectionString); //var contacts = db.Query<Contact>("SELECT * FROM Contacts"); var contacts = db.Query<Contact>("SELECT * FROM Contacts WHERE Id = @Id", new {id=1}); foreach (var item in contacts) { Console.WriteLine(item.ToString()); } Console.WriteLine("Done."); Console.ReadLine(); }

A very simple way to query the db using EF and Dapper.
class ContactsContext : DbContext { public ContactsContext(string connectionString) : base(connectionString) { } public DbSet<Contact> Contacts { get; set; } }

EF’s context
public class Contact { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public string Company { get; set; } public string Title { get; set; } public override string ToString() { return string.Format("{0} - {1} {2} ({3}) - {4} ({5})", this.Id, this.FirstName, this.LastName, this.Title, this.Company, this.Email); } }

Defining a contact
<connectionStrings> <add name="contactsDB" connectionString="server=.\;database=ContactsDemoDB;Trusted_Connection=Yes;" providerName="System.Data.SqlClient" /> </connectionStrings>

db connection string

Setting up the DB

image

In a DB project, can set a post deploy script to seed data (in the properties of the file)

image
Using SSMS Database Diagram

Ordered Tests

image
A way of running the tests in order.  Maybe should wrap in a transaction, or run db scripts so if in the middle, it will get db state back to the start.  Or maybe not use them

Features of Dapper

  • Speed! (almost as fast as raw ADO.NET DataReader)
  • Mapping from db columns to properties of CLR objects
  • Sprocs
  • Rich community of Contrib projects..
private IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["ContactsDB"].ConnectionString); public Contact Find(int id) { // Use Anonymous types typically // SingleOrDefault so if its not found it will return a null return db.Query<Contact>("SELECT * FROM Contacts WHERE Id = @Id", new {Id = id}).SingleOrDefault(); } public List<Contact> GetAll() { return db.Query<Contact>("SELECT * FROM Contacts").ToList(); } public Contact Add(Contact contact) { var sql = "INSERT INTO Contacts (FirstName, LastName, Email, Company, Title) VALUES (@FirstName, @LastName, @Email, @Company, @Title); " + "SELECT CAST(SCOPE_IDENTITY() as int)"; var id = db.Query<int>(sql, contact).Single(); contact.Id = id; return contact; } public Contact Update(Contact contact) { var sql = "UPDATE Contacts " + "SET FirstName = @FirstName, " + " LastName = @LastName, " + " Email = @Email, " + " Company = @Company, " + " Title = @Title " + "WHERE Id = @Id"; db.Execute(sql, contact); return contact; } public void Remove(int id) { db.Execute("DELETE FROM Contacts WHERE ID = @Id", new {id}); }

Add method – notice am using the object Contact, which matched up to the db columns, so don’t have to specify the parameters. Annoying that have to write boilerplate SQL ie for the INSERT

Addresses Child Table

1 contact can have multiple addresses

public Contact GetFullContact(int id){ var sql = "SELECT * FROM Contacts WHERE Id = @Id; " + "SELECT * From Addresses WHERE ContactID = @Id"; using (var multipleResults = db.QueryMultiple(sql, new {id})){ var contact = multipleResults.Read<Contact>().SingleOrDefault(); var addresses = multipleResults.Read<Address>().ToList(); if (contact != null && addresses != null){ contact.Addresses.AddRange(addresses); } return contact; } }

Creating a contact with addresses hydrated using 1 round trip to the db.

Instead of saving each entity – we’ll save the parent entity which is hydrated.

public void Save(Contact contact) { using (var txScope = new TransactionScope()){ if (contact.IsNew){ Add(contact); } else{ Update(contact); } foreach (var addr in contact.Addresses.Where(a => !a.IsDeleted)){ addr.ContactId = contact.Id; if (addr.IsNew){ Add(addr); } else{ Update(addr); } } // if delete an address off an existing contact foreach (var addr in contact.Addresses.Where(a => a.IsDeleted)){ db.Execute("DELETE FROM Addresses WHERE Id = @Id", new {addr.Id}); } txScope.Complete(); } }

Quite nice as easy to see what is going on, and wrapped in a transaction.

Durandal UI

He’s done a nice simple SPA UI    ,                                                       

Bulk Insert

ie a list<contacts> with a single INSERT.. behind the scenes though.. multipletrips to the db.. just nice sugar

List Support

ie SQL - IN

| | #