Happy Holidays!

Saturday MP (i.e. Chris and Ada) are taking some time off over the holidays to visit with family, friends, and spending a day not changing out of our pyjamas and playing games all day.  We will be back to our regularly scheduled programming on January 2nd, 2019.

Happy holidays and all the best in 2019!

Old Timey Record Player

P.S. – My daughter wanted a record player for Christmas.  I know, everything old is new again.  Lucky for my daughter she got the above old timey looking record player as an early Christmas gift when her Aunt and family where visiting this weekend.  Not only does it play records but is also plays tapes, CDs, radio, and Bluetooth.  Now we just need to get some records.

In honour of the great gift I present my daughters 2nd favourite Christmas song.

Posted in Fun | Tagged | Comments Off on Happy Holidays!

Today I Learned how to Generate a ERD for Rails Application

Back in the day Rails apps didn’t add foreign keys to database tables.  Believe it or not this was a feature not a bug.  The idea was that you shouldn’t “repeat” the relationship between you models in the code and in the database.  It wasn’t until Rails 4.2 that support was added for foreign keys.  

As you can probably guess I think this was a mistake.  If you have worked with a database without any foreign key constraints you quickly run into data integrity issues.  I don’t care how careful you think you are you will eventually screw up.  If not you then another person or application will corrupt your data.  Line items not attached to an order, address without customers, cats and dogs living together, etc.

It’s also harder to use tools on a database without foreign keys.  Reporting tools often relay on foreign keys to help the user create queries and display data.

Finally without foreign keys it’s hard to see how tables are related to each other.  You can’t just generate a ERD.  While you can, but you end up with just a bunch of tables with no idea how they are related to each other.  This is the problem I’m currently having with a database for a Rails 3.2 application.  How can see the relationships between the tables?

What I need is a tool that can read the relationships between the models in the application.  Lucky for me this tool exists and is called Rails-ERD.

You can find the install instructions here.  In my case I had a Rails 3.2 application running in a Docker container but that was client code that I can’t show here.  Instead my example will be the Saturday MP website which is Rails 4 with foreign keys but will work fine for this example. 

My website also uses Docker.  If you don’t use Docker then just run the commands on you local machine.  First step is to update the Dockerfile to install Graphviz.

Then add the rails-erd gem to the Gemfile.  Just add it to development as we don’t need it for tests and production.

Then rebuild the container to install Graphviz and the Rails-ERD gem.

Since we are using Docker we first need to spin up our container then ran the rake command to create the ERD.

docker-compose run web bash up

rake erd

This will create a PDF version of your ERD.  If you have a small ERD, like my website, then you are done. 

If you have a larger ERD, like the client code I can’t show you, then you are not done as the ERD will be unreadably small if you print it.  Printing things is something old men with bad eyes like to do.  What you can do is break up the database into sections.  For example, we could just show the product part of my database with the following command:

rake erd filename="products_erd" title="Saturday MP Products ERD" only="Product,ProductVersion"

What I like to do is create a batch file that will generate all the ERDs and but it in the databases folder.  Then you can run this batch file whenever you update the database to generate updated ERDs.

#!/usr/bin/env bash
rake erd filename="erd" title="Saturday MP ERD"
rake erd filename="products_erd" title="Saturday MP Products ERD" only="Product,ProductVersion"

Thanks for Voormedia for creating Rails-ERD and sharing it.

P.S. – About a month ago we saw The Once live and they sang the below song.  Actually, they got the the audience to sing the “By the glow of the kerosene light” part.  Weirdly it got really dusty in the theater at the end of the song because everyones eyes where watery, including the bands.

And sometimes love bloomed and sometimes dreams die
By the glow of the kerosene light.

By the glow of the kerosene light.

Posted in Code Examples, Software Development, Today I Learned | Tagged , , , | Comments Off on Today I Learned how to Generate a ERD for Rails Application

Introduction to ORMs for DBAs: Part 6 – Create GamesPlayed Table and CRUD

I gave the Introduction to ORMs for DBAs presentation at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

In the previous post we created the Games Results Type table and CRUD methods.  This table stores the possible outcomes of a game (i.e. win, lose, or tie).  In this post we will create the Game Played Table and CRUD.  This table tracks when a game was played but does not track who played the game.  More on that later.

If you skipped the previous post but want to follow along open up 06 – Create GamesPlayed Table and CRUD.  Then run the migrations to create the Player, Games, and GameResultTypes tables in the database.  Your database similar to the below screen shot.  The migration IDs can be different but the tables should exist.

Part 6 Initial Database

After completing Part 5 our database has the edge tables completed (Players, Games, and GameResultTypes) but none of the central tables (GamesPlayed and GamePlayers).  Lets start with our second most important edge table, the GamesPlayed table.

Game Tracker ERD

As usual we will start by creating the model.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace SaturdayMP.GameTracker.Models
{
    [Table("GamesPlayed")]
    public class GamePlayed
    {
        public int Id { get; set; }

        public int GameId { get; set; }
        public Game Game { get; set; }

        public DateTime DatePlayed { get; set; }
    }
}

This should look similar to the other models we have created so far with one minor difference.  This model is part of a one-to-many relationship with the Games table.  One game can be played many times. 

The below line is what links our new model to the Games table.  It says a GamesPlayed record belongs to a Game record.

public int GameId { get; set; }
public Game Game { get; set; }

Entity Framework, and most other ORMs, are smart enough to correctly map a reference to another model as a foreign key.

This relationship goes both ways and the relationship needs to be added to the Games table as well.  In this case it says a Game record can have many GamesPlayed records which is why a list is used.

public ICollection<GamePlayed> GamesPlayed { get; set; }

With the model created lets generate the migration.  This command should be familiar by now if you have been following along since the beginning.

dotnet ef migrations add CreateGamesPlayedTable

Checking the created migration we can see the foreign key created.

Run the migration on the database to create the new table.

dotnet ef database update

Next lets create the CRUD.

dotnet aspnet-codegenerator controller -name GamesPlayedController -outDir Controllers -m GamePlayed -dc GameTrackerContext -udl

Remember if the files don’t appear in the solution you might need to close the solution and re-open it.

To see our new CRUD methods we need to add the menu item to Layout.cshtml file.

<li><a asp-area="" asp-controller="GamesPlayed" asp-action="Index">Games Played</a></li>

Add Games Played Menu to Layout

Now lets run the application and navigate to the Games Played page.  Assuming you have a couple games created you should see something similar to the below.  If you don’t have any Games created, go to Games page first and add a couple.

Games Played Page with Game ID

Notice that the Game is linked to the Game ID?  That is not very user friendly.  We should show the name of the game instead. 

Lets start with the Index page.  Open up the page can change the following line so it references the name of the game instead of the ID. 

NOTE: you don’t need to stop running the application.  After your change you can just reload the page in your browser and see you changes.  Just make sure you have saved your changes you might have to hold down the Shift key when reloading the browser.

@Html.DisplayFor(modelItem => item.Game.Name)

That looks better.  Next up the Create page.  If we open up the view we don’t see a reference to the GamesPlayed object.  Instead we see a ViewBag.  This ViewBag contains a list of Games that we want to populate the dropdown with.

To show the game name in the create view we need to make changes to the controller.  Open up the GamesPlayedController and find the Get Create method.  Notice the creation of the ViewData?  ViewData and ViewBag are just different way of referencing the same data.  For some reason the Microsoft scaffolding decided to not be consistent.

The SelectList method is helper method to generate a list of data for populating a dropdown.  It takes a list of objects and what field you want to use as the key (DataValueField) and what field to display (DataTextField) to the user.  Currently the ID field is used as both the data and text fields.  To show the game name change the DataTextField argument, the 2nd one, to “Name”.

When you make changes to the controller you have to restart your application.  You can’t just reload the we page like we did when we made changes to the view.

Restart the application and create a new game played and it should now show the name of the game instead of the ID.

There are 3 more views that need to fixed: Details, Edit, and Delete.  In all cases the changes are similar to the ones we have done above.

To fix the Games Played Details update the view.  Change the Game.Id to Game.Name.

For the edit we need to update the SelectList to show the name but we have to do this in two spots.  The first is the Get and the second is the Post methods of Edit.

Finally we need to update the Delete page to show the name by updating view:

The Games Played section is now complete.  In the next post we will create the Game Players table.  This table will be the most complicated table so we will just create the table and save the CRUD for later.  It should also result in a smaller blog post.

If you got stuck you can find completed Part 6 here.  If you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 6 – Create GamesPlayed Table and CRUD

Introduction to ORMs for DBAs: Part 5 – Create GameResultTypes Table and CRUD

I gave the Introduction to ORMs for DBAs presentation at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

In the previous post we created the Games CRUD and the post before that we created the Games table.  In this post we will create both the GameResultTypes table CRUD methods. 

If you skipped the previous post but want to follow along open up 05 – Create GameResults Table.  Then run the migrations to create the Players and Games table in the database so your database similar to the below screen shot.  The migration IDs can be different but the tables should exist.

Player and Games Table Exist

Now that we can store tables and players we can start thinking about how to store the games our players have played.  When a game is played we need to store the game that was played, who played in the game, and who won.  A first draft for our data model might look like:

Game Tracker ERD Without GameResultTypes

Actually we can’t just track who won as there are three possible outcomes for a game: win, loss, and tie.  Depending on the game it’s possible to have multiple winners, losers, and ties.  For example, a cooperative game like Sentinels of the Multiverse either everyone wins or everyone loses.

We need a table that can track if a player lost, won, or tied a game.  A type table for the results of a game.  Our new data model looks like:

Game Tracker ERD Without GameResultTypes KeyCode

One problem developers and report writers have with type tables is determine what record stands for what type.  For example, what record in the GameResultTypes represents a Win?  How would you query for all the games a player won?

One possible way is to query on the string column:

Select *
From GamesPlayed gp
Inner Join GameResultTypes grt On gp.GameResultTypeId = grt.Id
Where gp.PlayerId = #
And grt.Type = 'Won'

This is a bad idea as the text could change.  How about the ID?

Select *
From GamesPlayed gp
Inner Join GameResultTypes grt On gp.GameResultTypeId = grt.Id
Where gp.PlayerId = #
And grt.ID = 10

Using an auto-increment ID as the identifier is a bad idea as it is set by the database and can change.  This is especially problematic as the database is migrated between environments such as from test to production.

How about not auto-incrementing the ID field?  That would work but I’m not a fan.  I prefer all the ID columns in my database to consistent.  I also prefer not to hard code IDs.  It should be up to the database to decide what the ID value is.  The only time I reference an ID is after I’ve retrieved the record via a non-ID search.

My preference is to have a field called KeyCode.  This is a unique integer field with a value that is set when the record is entered and never changed.  It can then be used whenever you need to access that particular type.  For example, if we assign the Win Game Result Type a Key Code of 10 then we can find all the games a player won by:

Select *
From GamesPlayed gp
Inner Join GameResultTypes grt On gp.GameResultTypeId = grt.Id
Where gp.PlayerId = #
And grt.KeyCode = 10

That means our GameResultTypes table now looks like:

Game Tracker ERD

Lets create a Game Result Type model for what we have so far.

using System.ComponentModel.DataAnnotations;

namespace SaturdayMP.GameTracker.Models
{
  public class GameResultType
  {
    public int Id { get; set; }

    public int KeyCode { get; set; }

    [MaxLength(10)]
    public string Type { get; set; }
  }
}

Initial Game Result Type Model

Another common feature of type table is we sometimes know all the records they will contain.  In this case they will only contain win, lose, and tie.

In software if we have a set amount of known types we can wrap them in an enum.  At it’s core an enum is really an integer but it only allows certain values.  For example, we can have colour enum that only allows certain colours:

public enum Colors
{
  Red,
  Blue,
  Green
}

Lets create an enum for our game result types in our model.  We could put in a seperate file but in this case the enum only exists because of the GameResultTypes so lets add it in the same file.

public enum GameResultTypes
{
Win = 10,
Loss = 11,
Tie = 12
}

Game Result Type Model with Enum

If we don’t assign numbers to the enums they will be auto assigned.  In this case the enums will be set to the KeyCode field so we want to know what these values are.

Now that we have the enum lets update our model with some syntatic sugar to make it easier to work with the enums.

using System.ComponentModel.DataAnnotations;

namespace SaturdayMP.GameTracker.Models
{
  public enum GameResultTypeEnums
  {
    Win = 10,
    Loss = 11,
    Tie = 12
  }

  public class GameResultType
  {
    public GameResultType()
    {
    }

  public GameResultType(GameResultTypeEnums @enum)
  {
    KeyCode = (int)@enum;
    Type = @enum.ToString();
  }

  public int Id { get; set; }

  public int KeyCode { get; set; }

  [MaxLength(10)]
  public string Type { get; set; }

  public static implicit operator GameResultType(GameResultTypeEnums @enum) =&amp;amp;gt; new GameResultType(@enum);

  public static implicit operator GameResultTypeEnums(GameResultType gameResultType) =&amp;amp;gt; (GameResultTypeEnums)gameResultType.Id;
  }
}

Complete Game Result Types Model

Notice that we still have the KeyCode field as a integer.  Some ORMs allow you to use enums but currently Entity Framework Core does not allow this.

The couple lines at the bottom simplify the conversion of the GameResultTypeEnums to the GameResultType object so we can write something like:

// Convert enum to model object.
GameResultType gameResultObject = GameResultTypeEnums.Win;

// Convert model object to enum.
GameResultTypeEnums gameResultTypeEnum = gameResultObject;

Now that the model is complete we can create the actual table in the database using this now familiar commands to create the migration:

dotnet ef migrations add CreateGameResultTypesTable

Create Game Result Types Migration
Game Result Type Migration

Then apply the migration:

dotnet ef database update

Update Database with Game Result Types Table
GameResultTypes Table in Database

Since we know that this table will only hold 3 records and we know what they are lets seed them.  To do this create a new class in the Data folder and call it DbInitializer.  In our new class create the Initialize method that will seed the data.

using System;
using System.Linq;
using SaturdayMP.GameTracker.Models;

namespace SaturdayMP.GameTracker.Data
{
  public static class DbInitializer
  {

    public static void Initialize(GameTrackerContext context)
    {
      if (context.GameResultTypes.Any())
      {
        // DB has already been seeded.
        return;
      }

      // Seed the Game Type Enums.
      foreach(GameResultTypeEnums result in Enum.GetValues(typeof(GameResultTypeEnums)))
      {
        context.Add&amp;lt;GameResultType&amp;gt;(result);
        context.SaveChanges();
      }

    }
  }
}

DbInitializer Class

The first if statement checks if the data has already been seeded.  If it has, then don’t seed it again.  The second part loops over all the GameResultTypeEnums and creates a record in the database.

Now we need to call our DbInitializer.  Lets do this when our application starts up in the Main:

var context = services.GetRequiredService&lt;SaturdayMP.GameTracker.Data.GameTrackerContext&gt;();
DbInitializer.Initialize(context);

Initialize Database in Main

Now if you start the application the GameResultTypes table will be populated.

GameResultTypes Table in Database

Notice that we don’t have any screens to edit GameResultTypes.  Lets stop the application and add our CRUD methods. Again this command should now be familiar:

dotnet aspnet-codegenerator controller -name GameResultsTypeController -outDir Controllers -m GameResultType -dc GameTrackerContext -udl

Command to Add Game Result Type CRUD

Unlike the other tables we have created we want to limit the actions that can be done to the GameResultTypes table.  Since we know it should only have 3 records which are seeded when the application is started we don’t need the Insert or Delete controller methods.  Lets remove them:

Delete Game Result Controller Create Method
Delete Game Result Controller Delete Method

We also need to remove the views for these methods:

Delete Game Results Type Create and Delete Views

Finally lets change the Edit view so the user can only change the description of the type.  The user shouldn’t be able to change the KeyCode.  The quickest way to do this is make the input control for the KeyCode to be read-only in the Edit view:

Make KeyCode ReadOnly in Edit View

Finally lets add a menu item so we can easily get to the Game Results Type pages:

Adding Game Result Types Menu

Run the application and you should be able to edit just the text of the game results:

Game Results Index
Game Results Edit

In the next post we will create the Games Played table and CRUD methods.  This is one of the the central tables of the application, second only to the Game Players table.

If you got stuck you can find completed Part 5 here.  If you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 5 – Create GameResultTypes Table and CRUD

Today I Learned how to Create Rails Docker Container Without Ruby Installed

I was curious to see if I could create a Docker container for a new Rails project without having Ruby or Rails installed on the host machine.  To do this I created a new Ubuntu 18 virtual machine with the bare minimum installed for the OS.  I also install Docker, RubyMine, and DataGrip.

Initially I was hoping I could just create the new project inside RubyMine.  Unfortunately I couldn’t get it working.  As you will see setting up the initial Docker container requires more then just running the “docker-compose up” command.

My main resource in setting up the image was Docker Rails Quickstart Guide.   The basic plan is:

  1. Setup Ruby Docker container.
  2. Add default Gemfile for Rails.  Required to create new Rails application.
  3. Create a new Rails application but don’t build the container yet.
  4. Update the configuration files.
  5. Build the docker container to install the Gems.

I started off as they recommended and created an empty folder with Dockerfile.

FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /website
WORKDIR /website
COPY Gemfile /website/Gemfile
COPY Gemfile.lock /website/Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY . /website

Dockerfile for Rails Container

I then created a basic Gemfile and empty Gemfile.lock file.

source 'https://rubygems.org'
gem 'rails', '5.2.0'

Initial Gemfile

Finally I created the docker-compose file.

You might have noticed this file is a bit different then the one in the Docker Quickstart.  I made these changes after the contain failed to build and/or I couldn’t connect to it with RubyMine.

version: '2'
services:
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: password1234
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/website
    ports:
      - "3000:3000"
    depends_on:
      - db

Docker Compose

The first change I made was downgrading the version from 3 to 2 as RubyMine currently only supports 2.  I also added ports and a password for the Postgres database so I can access from DataGrip.  If you don’t set the port and password your Rails application will be able to access the database but nothing else will.

I then created the rails application as recommended by the quickstart guide.  Since this is the first time running it pulls down the docker files.  Then I ran into the first of many permission errors.

docker-compose run web rails new . --force --database=postgresql

Creating new Rails App Cmd

First Permission Error

This permission error was caused by the Postgres container.  The files created Docker images are usually owned by root but some of the temporary Postgres files where also owned by VBoxAdd.

Database File Owned by VBoxAdd

After a while I figured out the way to fix this was to run the following command:

sudo chown -R $USER:$USER .

I got several permission errors during my trails and error of setting up the Rails container.  Every time I would just run the above command to fix it.

Once the permission errors went away I was able to create a new rails application.  Before the files for the new rails application where created it needs to build the Docker container so don’t be surprised to see the below.

Building Rails Container

Your newly created rails files might be owned by root.  In this case run the command you have probably become very familiar with:

sudo chown -R $USER:$USER .

Notice that the Gemfile has been updated and populated with all the Gems needed to run a new rails application.

Gemfile Populated by Rails New

Since we just called run on the web Docker container non of the installed Gems where saved in the container.  To prevent having to re-install the gems every time the container is run we need to build it.

Build Containers

Now the web container is ready but our database isn’t.  Open up the database config file and set the host, username, and password.

Database Config File Settings

Now create the Rails databases.

docker-compose run web rake db:create

Create the Rails Databases

Again if you get permission errors trying to create the databases run change permissions command.

sudo chown -R $USER:$USER .

Now bring up the containers and you should be see the Welcome to Rails website.

docker-compose up

Docker Compose Up

Yay Your are on Rails

The site is working but now we need to get it working with RubyMine.  If you use a different editor then your steps might be different.

First stop the containers using Ctrl-C.

Stopping Containers

To safe us some steps later lets update the Gemfile.  By default Rails installs the Byebug gem for debugging.  RubyMine likes the Ruby Debug IDE gem.  Just don’t run them both at the same time as they don’t play well together.

Remove ByeBug from the Gemfile and add Ruby Debug IDE.  Your Gemfile will look like:

Ruby Debug IDE Added to Gemfile

Now rebuild the Docker container so the new gems are installed.

docker-compose build

Then open up RubyMine and open up your project.  Once it’s open we need to tell RubyMine about our Docker containers.  To this go to File–>Settings.  Then go the Build, Execution, Deployment–>Docker in the Settings dialog and make sure Docker is setup correctly.  If it is you should see something similar to the below.

Docker Settings

Docker Settings Registry

You might be missing Docker Machine in which case you can install it following these instructions.  Try re-opening RubyMine and if it still does not find Docker Machine then you will need to tell it the exact path.

Now that Docker is setup correctly in RubyMine we need to setup the Ruby SDK by going to Languages & Frameworks –> Ruby  SDK and Gems in the Settings dialog.  Assuming you don’t have Ruby installed on your local workstation the list of Ruby SDKs should be empty.  Click the green plus sign to add one and choose New Remote.

Add New Remote Ruby SDK in RubyMine

In the Configure Remote Ruby Interpreter select Docker Compose and enter in the settings shown below.  This tells RubyMine what Docker Compose file to use to build the containers and container is the website.

Configure Remote Ruby Interpreter Dialog

After you click OK RubyMine will run the Docker containers and attempt to find Ruby in the container.  It will also attempt to find all the gems installed on the container.  This can take a couple minutes but if everything works correctly you should see something like:

Remote Docker Compose Ruby SDK Correctly Configured

Sometime the correct Ruby version will be listed by the gems won’t be shown.  To fix you might have to remove the newly added Ruby SDK by clicking the minus sign and try again.

If RubyMine can’t load the Docker containers then it will probably display a very unhelpful error message.  Try going back to the terminal and running docker-compose up manually.  If you get any errors fix them then try configuring RubyMine again.

Assuming everything is working correctly you should be able to run and debug the application.  To test that debugging works put a break point then try debugging.

Application Breakpoint

Run Debug Development

Application Breakpoint Hit

Now you can develop your new app without installing Ruby or Rails on your local workstation.  If you have any tips for dealing with the Docker Prostgres permission issues let me know at chris.cumming@saturdaymp.com.

P.S. – My wife recently introduced me to the band Walk of the Earth which we get to see live shortly.  They are most famous for all the band members covering Gotye’s “Somebody That I used Know” a single guitar but my favourite song is an original called “Rule the World“.

They said no way
I say I rule the world
(Ain’t afraid of the walls, I’mma break them down)
They stay the same
Well, I’m feelin’ high as a bird
(Ain’t afraid of the ground, I’mma stand up)

Posted in Code Examples, Software Development, Today I Learned | Tagged , , , , | Comments Off on Today I Learned how to Create Rails Docker Container Without Ruby Installed

Introduction to ORMs for DBAs: Part 4 – Create Game CRUD

I gave the Introduction to ORMs for DBAs at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

In the previous post we created the Games table and the post before that we created the Players table.  In this post we will create the CRUD methods to access the Games table.  

If you skipped the previous post but want to follow along open up 04 – Create Game CRUD.  Then run the migrations to create the Players and Games table in the database so your database similar to the below screen shot.  The migration IDs can be different but the tables should exist.

Player and Games Table Exist

Lets get right into it and create the CRUD scaffolding to access the games table.  I’ll create the scaffolding using the same command line I used to the create the Players CRUD scaffolding.

dotnet aspnet-codegenerator controller -name GamesController -outDir Controllers -m Game -dc GameTrackerContext -udl

Create Game CRUD

Just like the Player CRUD scaffolding you should see a GamesController and a bunch of Games views.  If you don’t see the views you might need to close Visual Studio and re-open it.

Game CRUD Created

I just realized we never talked the specifics of this command when we created the player CRUD so let’s do that now.  The first argument says we want to create a controller because the ASP.NET code generator can generate more then just controllers.  Then the “name” argument tells it the name of the controller.

Notice that we pluralize the name?  The model is singular because it represents on thing, in this case a game.  The Table is plural because it holds multiple games.  Finally the controller is plural because it’s the controller for all the games.  Of course you can pick your own standard.  Just be consistent.

Back to the command.  The “outDir” argument says where we want the controller to be created.  The “m” argument tells the scafolding what model to base the controller and views on.  The “dc” argument tells the code generator what data context to use.  Remember you can have more then one data context.  Finally the “udl” argument tells the generator to use our default layout file when creating the views.

Back to our application, we should run it to make sure it works but before we do that lets add the menu item to the Games page.  Open up the _Layout.cshtml file and add the following line:

<li><a asp-area="" asp-controller="Games" asp-action="Index">Games</a></li>

Add Games Menu

Now that the menu item has been added run the application and you should see the Games menu on the home page.

Games Menu Added

Click it an will take you to the Games Page index which shows a list of all the games.  Since there are no games yet the list is empty.  Click the Create New link and add a new game to make sure everything works.

Creating a new Game

New Game Created

Now that everything works lets get back to talking about the code and the ORM methods the controller.  For the PlayersController we talked about the Index, Details, and Create methods.  That leaves the Edit and Delete methods.

First up the Edit methods.  Notice I said methods as there are two Edit methods.  One Edit method to get the information about the game to be edited and the other saves the changes.  Lets start with the Get Edit method.

public async Task<IActionResult> Edit(int? id)
{
  if (id == null)
  {
    return NotFound();
  }

  var game = await _context.Games.SingleOrDefaultAsync(m => m.Id == id);
  if (game == null)
  {
    return NotFound();
  }
  return View(game);
}

 

Get Edit Game Method

The id argument passed into the method is the ID of the game to be displayed.  There is some error checking to make sure the id is not NULL.  Remember this is a website on the Internet and the Internet will often send you garbage (i.e. IDs that are not numbers).

if (id == null)
{
  return NotFound();
}

Assuming the id is a number we use Entity Framework to try and find the game in the database.

var game = await _context.Games.SingleOrDefaultAsync(m => m.Id == id);

This line of code tells Entity Framework to look in the games table and find any records that has the match the ID we are looking for.  The SingleOrDefaultAsync returns the game record if found or NULL if no record is found.  If multiple records are found then an exception is raised.  Basically it generates the following query:

Select *
From Games
Where Id = #

The found game record is then displayed to the user via the web page.  The user makes changes to the game, in this case changing the name, then submits the changes.  This submit calls the second Edit method which we call the Post Edit method.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Name")] Game game)
{
  if (id != game.Id)
  {
    return NotFound();
  }

  if (ModelState.IsValid)
  {
    try
    {
      _context.Update(game);
      await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
      if (!GameExists(game.Id))
      {
        return NotFound();
      }
      else
      {
        throw;
      }
    }
    return RedirectToAction(nameof(Index));
  }
  return View(game);
}

Post Edit Game Code

Quick aside, why am I calling the methods Get and Post?  They are terms used in the HTML protocal.  A GET request is used to retrieve data from the web server.  So in the case of the GET Edit method we want to “get” information about the game.  Post request is sending data to the webserver.  In this case we want to “post” the changes made to the game.

Back to the code.  First off what do these arguments mean?

public async Task<IActionResult> Edit(int id, [Bind("Id,Name")] Game game)

 

This first argument is the ID of the game we want to edit.  The second argument is the new values of the game.  The Bind in square brackets tells our application what fields to map to the Game object.  In this case it’s all the fields, the ID and Name.  In more complicated objects you might not want the user, especially a malicious user, to set certain fields.

Like the Get Edit method this method starts with some basic error handling.  First making sure the ID of the object to edit and the ID in the game object with the updated values are the same.  Remember we are dealing with Internet requests that might not be valid.

if (id != game.Id) 
{
  return NotFound(); 
}

Then it checks to make sure the updated values in the Game object are valid.  This is where you could also do business logic checking.

if (ModelState.IsValid)

Assuming all the error handling passes then the Game record in the database is updated.  The first line adds the updated Game object to the context.  Remember that changes to the context are written to the database when a save method is called.  In this case there is only one change.

_context.Update(game); 
await _context.SaveChangesAsync();

The actual saving is wrapped in a Try-Catch block to handle any errors in saving the edits.

That is it for the Edit methods.  Let us move on to the Delete methods.  First up the Get Delete method.

public async Task<IActionResult> Delete(int? id)
{
  if (id == null)
  {
    return NotFound();
  }

  var game = await _context.Games.SingleOrDefaultAsync(m => m.Id == id);
  if (game == null)
  {
    return NotFound();
  }
  return View(game);
}

 

Get Delete Game Method

Similar to the Get Edit method the Get Delete method simply finds the game we want to delete and returns it.  Presumably so the user can view the game before it’s deleted.  Nothing new to say so lets jump to the Post Delete method.

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
  var game = await _context.Games.SingleOrDefaultAsync(m => m.Id == id);
  _context.Games.Remove(game);
  await _context.SaveChangesAsync();
  return RedirectToAction(nameof(Index));
}

 

Post Delete Game Controller Method

Again the Post Delete method is very similar to the Post Edit method but in this case we don’t check if the game exists before deleting it.  The delete method with remove the game if it exists and if it does not exist then there is nothing to delete and no error is raised.

The SQL generated would look something like:

Delete From Games
Where Id = #

That is all for now.  In the next part we will create a table that has a one-to-many relationship and talk creating one-to-many ORM models.   If you got stuck you can find completed Part 4 here.  Finally if you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 4 – Create Game CRUD

Introduction to ORMs for DBAs: Part 3 – Player CRUD

I gave the Introduction to ORMs for DBAs at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

In the previous post we created the Games table and the post before that we created the Players table.  In this post we will create the CRUD methods to access the Players table.  

If you skipped the previous post but want to follow along open up 03 – Player CRUD.  Then run the migrations to create the Players and Games table in the database so your database similar to the below screen shot.  The migration IDs can be different but the tables should exist.

Player and Games Table Exist

In this post we will create some Create, Retrieve, Update and Delete (CRUD) methods to access the Players table.  To quickly create the CRUD methods we will use auto-generated scaffolding.  Scaffolding, in this context, is basic CRUD code.  In production you would expand upon the scaffolding but for this demo we will mostly leave it as is.  It’s a great way to get something up and running.

We will run the scaffolding from the command line but before we do that we need to add the Microsoft.VisualStuido.Web.CodeGeneration.Design NuGet package.

Adding Code Generation NuGet Package

Code Generation NuGet Package Added

Now that the package is added go the terminal and run the following command to make sure the new NuGet package is installed correctly.

dotnet restore

Now we can run the scaffolding commands.  Lets run it to create the Players CRUD methods.

dotnet aspnet-codegenerator controller -name PlayerController -outDir Controllers -m Player -dc GameTrackerContext -udl

Add Player Controller Scaffolding

Now go back to Visual Studio and you should see the PlayerController file and a bunch of Player views.  If you don’t see the player views then you might need to close Visual Studio and reopen it.

Player Controller and Views

Now lets test the scaffold pages.  Run the application and you will get the home page.  You need to manually enter the URL for the Players page.

http://localhost:port#/players

Player Index Page

You should be able to add, edit, and delete players as you like.

Creating Player Page

Let’s add a link to he Player pages on the home page.  Stop the application and open up the _Layout.cshtml file and add the following line just under the Home menu item:

<li><a asp-area="" asp-controller="Players" asp-action="Index">Players</a></li>

Adding Player Menu Item

Now run the application again you should see the Players link.  Click it to make sure it works.

Home Page with Player Menu Item

Now that the code is working we should talk about it a bit.  Since this is a ORM talk we will focus on the ORM code but we should quickly talk about the Model-View-Controller (MVC) pattern.

MVC is a software pattern that separates an application into three separate  parts.  You can probably guess what they are.  It’s easiest shown in the below diagram.

MVC Diagram

In this demo the views are the web pages the end user will see.  The files names created by the scaffolding say what the page does.  If we open one up, say the Index.cshtml, we will see mostly HTML mixed with some C# code as shown below.

Player Index View Code

When a web page is requested all the C# code is run on the webserver and translated into HTML before being sent to the browser.  In this example the C# code creates a row in the HTML table for every record it finds in the Players table.

@foreach (var item in Model)

The controller class are responsible for populating the views with data from the model.  They are also responsible for updating the model with new data submitted by the user.  If we look at the PlayerController we see there is scaffolding code to view all the players (the index method), create new players, view/edit existing players, and finally delete players.

Player Controller Code

Do you remember the GameTrackerContext class?  It is the link between the database and the application.  You can see it it passed into the constructor, which is the first bit of code that is executed when a class is instantiated.

public PlayersController(GameTrackerContext context)
{
  _context = context;
}

In this case the constructor takes the context and saves it so other methods in the class can use the context.  For example, the Index method uses the context class to retrieve all the records from the Player table.

 
// GET: Players
public async Task<IActionResult> Index()
{
  return View(await _context.Players.ToListAsync());
}

Player Controller Code Index Method

It’s the same as writing:

Select * From Players

The context takes the player data and maps it to the Player models.  The mapping is done by the ORM, in this case by Entity Framework.  The query is also generated by the ORM.  This is one on of the reasons developers like ORMs so much.  All this grunt work is handled for them.

Yes, I know selecting all the records from a table is not a feasible long term.  Remember this is scaffolding code.

Now let’s take a short look at the Details method.

// GET: Players/Details/5
public async Task<IActionResult> Details(int? id)
{
  if (id == null)
  {
    return NotFound();
  }

  var player = await _context.Players
    .SingleOrDefaultAsync(m => m.Id == id);
  if (player == null)
  {
    return NotFound();
  }

  return View(player);
}

Player Controller Code Details Method

This little bit of code finds on particular Player based on their ID.  It’s the same as writing:

Select * From Players Where Id = #

In this case it either finds the player in the database and maps it to the player model or it returns Null.  Again ORM did all the grunt work.  The developer didn’t have to write the query or the mapping code.

You are starting to get the idea but let’s look at one more, the Create method.  There are two Create methods, the first one simply returns the page for the user to enter the new player.  The second method is what is called when the user submits the create player page.  We are interested in the second method.

// POST: Players/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name")] Player player)
{
  if (ModelState.IsValid)
  {
    _context.Add(player);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
  }
  return View(player);
}

Player Controller Code Create Method

This method creates a new player in the database.  In this case the ASP.NET MVC populates the model from the information the user entered on the web page.  Then the code adds the new player to the context.  The context does not actually save the new player to the database until the SaveChangesAsync method is called.

As a DBA you can probably guess why the context does not save the changes immediately to the database.  It would result in lots of connections and queries which is very inefficient.  Instead the context the takes note of the changes should be made and then batch executes them in one connection.  If possible the ORM will also minimize the number of queries it needs send.  This is known as the Unit of Work pattern.

In this example we are just adding a single record in a Unit of Work but I’m sure you can imagine more complex scenario where several records in several tables are updated in one unit of work.

I think that is enough for now.  In the next post we will create the Games CRUD similar to above and discus the Edit and Delete methods.  If you got stuck you can find completed Part 3 here .  Finally if you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 3 – Player CRUD

Introduction to ORMs for DBAs: Part 2 – Games Table

I gave the Introduction to ORMs for DBAs at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

In the previous post we created the Players table and in this post we will create the Games table.  If you skipped the previous post but want to follow along open up 02 – Player Table.  Then run the migrations to create the Players table in the database so your database similar to the below screen shot.

Player Table With Max Length

Your migration IDs will be different but you should have a player table.

We will create the Games table the same way we created the Players table in part 1.  First create the Game model and add the Id and Name fields.  Since this is a simple database we will only track the name of the game.  No need to track the publisher, type, etc.

using System.ComponentModel.DataAnnotations;
namespace SaturdayMP.GameTracker.Models
{
  public class Game
  {
    public int Id { get; set; }

    [MaxLength(50)]
    public string Name { get; set; }
  }
}

Game Model

When setting up the Player table we intentionally forgot to set the max length of the field.  This time we won’t forget and set it to 50 again.  If you get an error that MaxLength does not exist then make sure you have the following at the top your file:

using System.ComponentModel.DataAnnotations;

Now that the model exists we need to tell the database context about it.  Open up the GameTrackerContext and add our new Game model.

public DbSet&lt;Game&gt; Games { get; set; }

Game Added To Database Context

Compile the application just to make sure there are no typos.  Now switch to the terminal and create the migration like we did in part 1.

dotnet ef migrations add CreateGamesTable

Create Game Table Migration

Take a quick look at the migration to make sure it was created and is what we expect.  Should be very similar to the Players migration.

Create Game Table Migration

Back in lets apply the migration on the database.

dotnet ef database update

Run Game Table Migration

Remember this command will run all the migrations that have not already been run on the database yet.  So the CreatePlayersTable migration will be skipped because it has already been run.

Now open up your database client and check that the table was created.

Games Table in Database

That was much shorter then creating the Player table in part 1.  If you got stuck you can find completed Part 2 here.  In Part 3 we will CRUD methods and pages to access the Player table.  Finally if you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 2 – Games Table

Introduction to ORMs for DBAs: Part 1 – Create Player Table

I gave the Introduction to ORMs for DBAs at SQL Saturday 710 but it didn’t go as well as I would have liked (i.e. I had trouble getting my demo working).  Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  You can find the slides I showed before the demo here.

The goal of this demo is create a basic website that tracks the games you and your friends play and display wins and losses on the home page.  I used a MacBook Pro for my presentation so you will see Mac screen shots.  That said the demo will also work on Windows.

This post creates a Player table and all the setup to for Entity Framework.  To follow along open up the 01 – Create Player Table project.  If you need a hand getting the tools installed check out Part 0 – Setup.

We start with a blank ASP.NET MVC application.  It’s similar to what you get when you create a default ASP.NET MVC application in Visual Studio but I’ve deleted some unneeded files related to the About and Contacts pages.

Empty ASP.NET Visual Studio

If we run the application we will a home page where we eventually want to display the Win/Lose table for the players.

Starting Web Project Home Page

Now lets make sure our database is up and running.  Since we running the demo on a Mac we need to run SQL Server inside Docker.  There is Docker Compose file in the root folder so we can run the below command to start SQL Server:

 
$ docker-compose up

Bring Up SQL Server

We will use DataGrip as our SQL Client because it runs on Mac.  You could also use Microsoft SQL Operations Studio.  If we look at our database server we see it has nothing but the master database.

Empty Database Server

Everything seems to be working so lets start creating our application starting with the Player.

Define Player Model

To track what games people have played we will need to store information about the player and games being played.  Lets start with the player.

If you are a DBA you are itching to open up your SQL Client and create the Players table but we aren’t going to do that.  Instead we will use a feature in most ORMs called Code First.  You define your database model in code and let the ORM handle the database changes for you.

Define the Player model by creating a new class in the Models folder called Player.

Add Player Model

This class is our model and represents the Players table in the database.  Since this is a simple application used by friends we only need their name.   So our model will look like:

namespace SaturdayMP.GameTracker.Models
{
  public class Player
  {
    public int Id { get; set; }

    public string Name { get; set; }
  }
}

 

Player Model

This model defines that we have a Players table and it has two fields: Id and Name.  Notice I said the table name is Players with an “s” but the model name is singular.  Most ORMs have default conventions they use for dealing with names.  Entity Framework assumes your model name is singular and your table will be plural.  Entity Framework also assumes any field named Id will be a primary key.  Of course you can override the conventions if you want.

Setup Connection to Database

The model is now defined but before we can create the table we need a way for our application to access the database.

The first step is to create the database context.  The database context is how most of our code will interact with the database.  We will put the context class in the a new folder called Data and call our context GameTrackerContext.  If your application accesses more then one database you will have multiple contexts.

using SaturdayMP.GameTracker.Models;
using Microsoft.EntityFrameworkCore;

namespace SaturdayMP.GameTracker.Data
{
  public class GameTrackerContext : DbContext
  {
    public GameTrackerContext(DbContextOptions<GameTrackerContext> options) : base(options)
    {
    }

    public DbSet<Player> Players { get; set; }
  }
}

Game Tracker Context

The important part is the DBSet line.  This tells the database context to map the Player model to the underlying Players table.  As we add more tables we will add additional DbSet lines.

Next lets set the connection string.  Do DBAs have to deal with connection strings or is it a developer thing?  Anyway, the connection string is set in the aspsettings.json file:

"ConnectionStrings": {
  "DefaultConnection": "Server=(local);Database=GameTrackerDemo;Trusted_Connection=False;User ID=sa;Password=Password1234!"
}

Setting Connection String

We won’t see the effects of this next step till later but we will do it now as we are doing all our setup now.  We need to tell the website that we have a database context and that it should automatically include it in controllers.  This is done in the Startup.cs file.  Add the following to the ConfigureServices method.

services.AddDbContext&lt;SaturdayMP.GameTracker.Data.GameTrackerContext&gt;(
 options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

Adding DB Context To Service

Setup Command Line Tools

This next step is a bit of pain.  As of this writing all the cool menu items in Visual Studio on Windows are not available for Visual Studio for Mac.  We have to use the command line and this requires us to manually edit the project file.

Close Visual Studio then find the SaturdayMP.GameTracker project file and open it up in a text editor.

Game Tracker Project File

Then add the following two lines, one to the PackageReference ItemGroup and the other to the DotNetCliToolReference ItemGroup:

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" />
</ItemGroup>

<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.2" />
</ItemGroup>

 

Add EF CLI Tool to Project File

Now reopen the the solution in Visual Studio and rebuild the solution.  If you got any errors check that you put the lines in the correct spot and didn’t forget a double quote or greater/lesser then character.

Open up a new terminal and navigate to the folder where your project is located.  Then run the following command to make sure the command line tools are loaded and installed:

 
$ dotnet restore

To test if everything works run the below command.  It should show something similar to the screenshot below.

 
$ dotnet ef

 

.NET EF Command Success

Generate Player Migration

Now we can generate the Player table.  Actually we will generate a migration that will generate the Player table.  A migration is file that contains changes we want to make to the database such as creating tables, add/removing columns on existing tables, adding indexes, etc.

dotnet ef migrations add CreatePlayerTable

Create Player Migration File

Make sure you are in the project folder when you try to run the command or it will fail.  Assuming it succeeded you should see a Migrations folder in Visual Studio and one file in it that ends in “CreatePlayerTable”.

Player Table Migration File

If we open up the file we see it does not contain SQL but C# code.  The reason for using C# is so the same migration file can be run against different databases such as Oracle, PostgreSQL, etc.  Even if you don’t understand C# it should be pretty clear that this file is creating the Player with the Id and Name fields.

A migration file contains contains changes you want to apply to a database.  They can be manually created but in this case we used Entity Framework to create it.  It created the migration file by comparing what the database currently looked like to what it should look like based on the models defined in code.  In this case the the database is empty (non-existent) but we have a Player model defined thus the thus the migration file creates the player table.

Run the Player Table Migration

Now we can run the migration to create the table in the database.

dotnet ef database update

Run Player Table Migration

The above command will actually run all the migrations we have defined.  Currently we only have one so it only runs the one.  If we switch to our SQL client and refresh we should see the new Player table in the database.

Show Game Tracker Demo Database

Player Table in DataGrip

Notice the _EFMigrationHistory table?  This table tracks what migrations have been run on this database.  If a migration has already been run on the database it won’t be run a second time.

Drop and Recreate the Migration File

One thing you DBAs probably noticed is the Name field is set to max length, which is not good.  Lets change it to 50 characters.

In this case we haven’t shared our migration with anyone else yet so we can delete the migration and try again.  If we had pushed this migration to our code repository we would have to create a new migration to undo our previous one.

If you remember the migration file had an up and a down.  The down part is run if you un-apply the migration.  In this case it will drop our table.

Lets ask Entity Framework to unapply our migration.  In the below example we say we want to undo all the migrations but you can specify specific migrations to undo.

dotnet ef database update 0

Reversing Create Player Migration

Now if we refresh in our SQL Client the database still exists but the Players table has been dropped.

Player Table Dropped

The Player table has been removed from the database but we still need to remove the migration.  It’s best if we let Entity Framework remove the migration for us.  The below command will remove the last migration file created.

dotnet ef migrations remove

Remove Create Player Migration

Migration Removed

Since it was the only migration file the Migrations folder was also removed.  If we had other migrations the folder would not have been removed.

Now that we have cleaned everything up go to the Player model and set the max length to 50 and save your changes.

[MaxLength(50)]
public string Name {get; set; }

 

Add Max Length to Name on Player Model

Now recreate the migration file.

 
dotnet ef migrations add CreatePlayerTable

Create Player Table Migration With Max Length

Create Player Migration With Max Length

Notice that the max length is set in the migration file?  Now apply this migration.

dotnet ef database update

Run Create Player Migration With Max Length

Refresh our database client and you should see Players table with a correct Name length field.

Player Table With Max Length

Whew, that was a lot of work.  The next part won’t be as long as we can skip a lot of the first time setup.

If you got stuck you can find completed Part 1 here and the completed application here.  In Part 2 we will create Games table similar to what we did above.  Finally if you have any questions or spot an issue in the code I would prefer if you opened a issue in GitHub but you can e-mail (chris.cumming@saturdaymp.com) me as well.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 1 – Create Player Table

Introduction to ORMs for DBAs: Part 0 – Setup

SQL Saturday LogoI gave a presentation at SQL Saturday 710 that didn’t go as well as I liked (i.e. I had trouble getting my demo working).  For those that attended thank you for patience.  Hopefully it was still worth attending and the discussion without the live coding was worth while.

Since the demo didn’t work live I thought I would show you what was supposed to happen during the demo.  The source code for the demo is here.

I used a MacBook pro for my presentation but the demo will also work on Windows.  Just be prepared for Mac screenshots.

First thing you need is Visual Studio 2017.  The community edition is free to use.  To install just keep clicking next.  It should install .NET Core 2.0, or higher for you.

Next you need to setup SQL Server.  You can find the steps to run SQL Server inside a Docker container here.  If you are on Windows the steps are similar just use the Windows SQL Server Docker image instead.

I used DataGrip as my client to access SQL Server but you can use Microsoft SQL Operations Studio instead.

Intro to ORM for DBAs Demo Steps

That is all you need to run the demo.  Future posts all walk through demo steps as outlined above.  If you have any questions open a issue in the GitHub repository.

Posted in Code Examples, Introduction to ORMs for DBAs, Software Development | Tagged , , , , , , | Comments Off on Introduction to ORMs for DBAs: Part 0 – Setup