Single Page Application (SPA) using AngularJS and WebAPI – Architecture

The goal of this post is to clarify an architecture of a single page application using the following technologies:

  • ASP MVC
  • AngularJS
  • WebAPI
  • Entity Framework

The next diagram shows at the left the client side and at the right the server side:

Single Page Application (SPA) using AngularJS and WebAPI – Architecture

 

 The first row is the communication between the different used technologies.

The middle row represent the logic of our application and the last the data containers used on these classes.

Using the previous diagram is easy to see which data each layer uses.

e.g:

  1. The Angular controller can only work with the Angular context.
  2. The WebAPI controller send and receive data in JSON format. The JSON objects are automatically translated to C# view models. The WebAPI controllers are also able to map the view-models to domain objects to use the domain services. WebAPI controllers can also request domain objects to the domain services and translate it to ViewModels c# before sending it back to the client-side in JSON format.

Data containers and layers:

  • AngularJS Context: The context is populated by the angular repository. HTML templates bind to it.
  • ViewModels Json: The data is sent from client to server side and vice versa in JSON format. The WebAPI controller send automatically by default the data in this format. The send and received data in JSON format is mapped automatically to the expected object.
  • ViewModels C#: The data the WebAPI controller send and receive as parameter. The conversion between Json and C# view models is done automatically by the WebAPI controller. This class is a subset of our entity domain objects plus some calculated properties that our views may need. It can be used for example to keep some server-side data hidden on the client-side.
  • Entities: Entity Framework entities or domain specific classes. All the data related to the domain. Theses classes are completely independent of the view. The domain services or application logic must use theses classes. The mapping from and to Entities to c# view models can be done automatically or Auto-mapper.

Entity Framework – Lazy Loading

I want to analyse in this post how Entity Framework really interact with the database. i.e. The queries that are really executed.

In previous post I created a database using Code First. These are two of my entities:

A food representation:

public class Food
{
    /// <summary>
    /// Gets or sets the food identifier.
    /// </summary>
    [Key]
    // NOTE: As the name is className + id, this property is not needed
    public int Id { getset; }
 
    /// <summary>
    /// Gets or sets the food name.
    /// </summary>
    [MaxLength(200)]
    [Index(IsUnique = true)]
    public string Name { getset; }
 
    /// <summary>
    /// Gets or sets the recipes needing this Food
    /// </summary>
    // NOTE: EF needs the virtual attribute to enable Lazy loading 
    public virtual List<Recipe> RecpiesNeedingThisFood { getset; }
 
    /// <summary>
    /// Returns a <see cref="System.String" /> that represents this instance.
    /// </summary>
    public override string ToString()
    {
        return string.Format("{0} ({1})"this.Name, this.Id);
    }
}

An entry on my fridge representation: a food and an expire date of this food.

public class FridgeEntry
{
    /// <summary>
    /// Initializes a new instance of the <see cref="FridgeEntry"/> class.
    /// </summary>
    public FridgeEntry()
    {
        ExpireDate = DateTime.MaxValue;
    }
 
    public int Id { getset; }
 
    [Required]
    // NOTE virtual is needed for lazy loading
    public virtual Food Food { getset; }
 
    /// <summary>
    /// Gets or sets the expire date.
    /// </summary>
    public DateTime ExpireDate { getset; }
 
 
    /// <summary>
    /// Returns a <see cref="System.String" /> that represents this instance.
    /// </summary>
    public override string ToString()
    {
        return string.Format("FoodId ({0}) - expire date: {1}"this.Id, this.ExpireDate);
    }
}

How to debug the queries and connections between EF and my database?

A new feature of EF6 is the possibility to log everything that Entity Framework is doing.

The context.Database has a Log property which is type Action<string> if this action is not null EF will call it always he connect to the database.

Define a logger, to analyse the Lazy loading a simple method writing in console the messages is enough:

private static void ConsoleLogger(string msg)
{
    msg = msg.Trim();
 
    if (!string.IsNullOrEmpty(msg))
    {
        Console.ForegroundColor = ConsoleColor.DarkGray;
        Console.WriteLine(DateTime.Now.TimeOfDay.ToString("g"));
        Console.ForegroundColor = ConsoleColor.DarkGreen;
        Console.WriteLine(msg);
 
        Console.ResetColor();
    }
}

Now we just have to define this  logger as the logger of the context.Database.

EF Lazy loading testing

We have already a way to see the connections between EF and the database, now let’s analyse it:

Continue reading

Entity Framework – Local and Azure connection

In previous posts I used EF using the local database and using the Azure SQL Server. This is the configuration I use now to connect to my local database in Debug mode and to my Windows Azure database in Release Mode.

App.config

  <connectionStrings>
    <!--Azure MyFood database-->
    <add 
        name="MyFoodAzure"
        providerName="System.Data.SqlClient"
        connectionString="Data Source=i608rt1tak.database.windows.net;Initial Catalog=MyFood;Integrated Security=False;User ID=ravened;Password=pass¿;Connect Timeout=60;Encrypt=False;TrustServerCertificate=False" />
    
    <!--Local MyFood database-->
    <add 
        name="MyFoodLocal"
        providerName="System.Data.SqlClient"
        connectionString="Server=(localdb)\v11.0;Integrated Security=true;Database=MyFood;"/>
  </connectionStrings>

DbContext

    public class FoodContext : DbContext
    {
 
        // NOTE: Call base constructor to specify the connection string name
#if !DEBUG
        // In Release mode it will look for the Cloud connection string
        public FoodContext() : base("name=MyFoodAzure") { }
#else
        // In Release mode it will look for the Cloud connection string
        public FoodContext() : base("name=MyFoodLocal") { }
#endif
 
        public DbSet<Food> Foods { getset; }
        public DbSet<Recipe> Recipes { getset; }
        public DbSet<FridgeEntry> Fridge { getset; }
 
    }

Azure SQL Server – Entity Framework Connection

By default when Entity framework is added to a project, a file “App.config” is created if it doesn’t exists yet.
( “Web.config” in web applications).
A default connection factory that will connect to a local database is added in this file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
 
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
  </startup>
 
  <!-- By default, when no connection string is specified use the local database.-->
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
 
</configuration>
  

This factory will be used when no connection string for the specified context is found. But let clarity how EF try to find the connection string to use…

Which connection string will EF use?

To connect to the database we use a context that extend DbContext.

By default if we don’t call a DbContext base constructor, E.F. will look for a connection string name using the name of our defined context.

namespace CodeFirstAzureTest.Data
{
    public class FoodContext : DbContext
    {
        public DbSet<Food> Foods { getset; }
        public DbSet<Recipe> Recipes { getset; }
        public DbSet<FridgeEntry> Fridge { getset; }
 
    }
}

It is possible to specify the name of the connection string or the complete connection string calling the base constructor:

using System.Data.Entity;
using CodeFirstAzureTest.Data.Entities;
 
namespace CodeFirstAzureTest.Data
{
    public class FoodContext : DbContext
    {
        // NOTE: Call base constructor to specify the connection string name
        public FoodContext() : base("name=MyFood") { }
 
        public DbSet<Food> Foods { getset; }
        public DbSet<Recipe> Recipes { getset; }
        public DbSet<FridgeEntry> Fridge { getset; }
 
    }
}

When no connection string is defined, if a defaultConnectionFactory is defined, EF will use it to create a connection string using the name of the connection string he needs.

e.g. If we don’t specify the connection string name in our context and EF cannot find any connection string the factory will create one using exactly this name. This is why by default the database created locally had this name in my previous post.

Connect EF to Windows Azure

To connect to a Windows Azure we need to do the following steps:

Continue reading

Entity Framework 6 – Migrations, Advanced Topics

In previous posts I created a database using EF code-first and I enabled migrations.

Now lets try some advanced topics:

  • Downgrades & migrations to specific  versions
  • Customizing Migrations
  • Execute custom SQL with the migration
  • Get migration generated SQL
  • Auto migrate when the application start and additional actions

Downgrades & migrations to specific  versions

To migrate to an specific version run in command in Package Manager Console.

Update-Database –TargetMigration: MigrationName

Customizing Migrations

Let’s add a couple of new properties to our Model and add a migration to generate the default migration. We will add some information to our recipes:

  • A name: the name shall be unique for each recipe.
  • A complexity index: each recipe shall have a complexity index from 1 to 3, the default complexity level shall be 2.

This is our new Recipe class with a name and complexity index:

public class Recipe
{
    // Primary Key
    public int RecipeId { getset; }
 
    // EF needs the virtual attribute to enable Lazy loading 
    public virtual List<Food> Ingredients { getset; }
 
    // Recipe description
    public string Description { getset; }
 
    // Recipe name
    [Index(IsUnique = true)]
    [MaxLength(200)] 
    public string Name { getset; }
 
    // Recipe complexity
    [Range(1, 3)]
    [DefaultValue(2)]
    public int Complexity { getset; }
}

Add the default migration:

PM> Add-Migration Recipe_NameAndComplexity
Scaffolding migration ‘Recipe_NameAndComplexity’.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running ‘Add-Migration Recipe_NameAndComplexity’ again.

Continue reading