tangible T4 Editor Blog

News, Tip and Tricks from the tangible T4 Editor team.

  • Home
  • Blog
  • Blog Series: Model Driven Development with T4 templates – Part 4

Blog Series: Model Driven Development with T4 templates – Part 4

 

This part of the Model Driven Development blog series creates persistence layer (based on SQL Server) for the domain specific model built in Part 2 of the series using the C# code classes for Entity Framework 5.0 generated by a T4 template in Part 3.

The next blog post will create a basic user interface for interacting with the data objects and storing them in a SQL Server relational database.

 

image

Blog Series Overview

Part 1: Model Driven Development and Series Overview

Part 2: Create a Persistence Model using Tangible Modeling Tools

Part 3: Generating Domain Specific data objects using T4 and EntityFramework 5 CodeFirst

Part 4: Data Persistence and Versioning

Part 5: Generate a Basic UI using T4 and Windows Presentation Foundation

 

In this Part

Create SQL Server Database for Domain Specific Model

Read and Write data

Migration

Different Providers

Continuation

 

Create SQL Server Database For Domain Specific Model

Connection to a SQL Server

First, make sure you have access to a SQL Server installation. You can download the SQL Server Express Edition for free here.

Then you need to get a connection string that lets the data context know where to create the database and to access data from our domain specific model. Using a SQL Server Express instance installed on your local computer that connection string might look like this:

“Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True;”

If you need assistance in what your connection string should look like – look at http://connectionstrings.com/

 

Database Initializer

As an example we’re going to use a Console Application that either contains our domain specific model file (.tasl) and the T4 template that generates the Entity Framework CodeFirst classes or references the assembly that does contain both.

So at the application startup the Entity Framework needs to know how to initialize the database for our domain model. At this moment we want to assure that the database is created when we intend to access it. For this purpose there is an existing Initializer class: System.Data.Entity.CreateDatabaseIfNotExists<T>, where T needs to be replaced by the Type of our Database Context class.

 

using System.Data.Entity;

public static class Program 

    public static void Main(string[] args) 
    { 
        System.Data.Entity.Database.SetInitializer<Context>(

             new CreateDatabaseIfNotExists<Context>());

        // access data here

    }

}

 

Create Context class

Now we can create an instance of the Context class generated by our T4 template we built in the last blog post. We can pass the connection string to our database in the constructor of the Context class. Since the Context class implements IDisposable, it should be used inside using-blocks:

 

using (var ctx = new Context(

      @"Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True;")) 
{

    // read and write data here
}

 

Read and Write data

Of course the database will be empty on the first call, so let’s start with writing data: We’re going to create two instances of the Bank class, add them to the context and save them in the database:

 

using (var ctx = new Context(

      @"Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True;"))

    var bank1 = new Bank() { Name = "Goliath National Bank" }; 
    ctx.Bank.Add(bank1); 
   

    var bank2 = new Bank() { Name = "ACME Bank" }; 
    ctx.Bank.Add(bank2);

   

    ctx.SaveChanges(); 
}

 

You don’t need to care about setting the Id-Property. We marked that property as the [Key] identifier in the database, so its set automatically and correctly.

If you open the SQL Server Express Management Studio you can have a look inside the database and its tables:

 

image

 

Now let’s add another bank and give it a customer, so that you get a feeling for how creating relationships between objects works:

 

using (var ctx = new Context(

      @"Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True;"))
{

    // create a bank 
    var bank3 = new Bank() { Name = "Awesome Bank" }; 
    ctx.Bank.Add(bank3);

   

    // create a customer and add it to the bank's customers collection 
    var customer1 = new Customer() { FirstName = "Joe", LastName = "Public" }; 
    bank3.Customers.Add(customer1);

    ctx.SaveChanges();
}

 

After having written some data, here’s how to retrieve data from the database. We’re going to iterate all banks and write their names to the Console output:

 

using (var ctx = new Context(

      @"Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True;"))

    foreach (var bank in ctx.Bank) 
        Console.WriteLine(bank.Name);
}

 

image

 

 

Database Migration

Its getting more interesting when we attempt to change the domain specific model after having created the database and filled it with lots of data. Should we now export the data, create a new database and enter all data again? Should we change the database schema manually?

Its easier than one might think. Entity Framework comes with more database initializers than only the CreateDatabaseIfNotExists initializer and there is one that supports schema evolution in the database and thus provides database migration for us. There are just a few more lines of code necessary to make the migration feature work.

 

First we need to create a new class that determines what database is to be migrated and how the migration process is parameterized. So create a new class called MigrationConfiguration and derive it from DbMirgrationConfiguration<Context>. In the constructor we decide what database to use and if migration is allowed.

 

sealed class MigrationConfiguration :

    System.Data.Entity.Migrations.DbMigrationsConfiguration<Context>
    {
        public MigrationConfiguration()
        {
            this.AutomaticMigrationsEnabled = true;
            //this.AutomaticMigrationDataLossAllowed = true;
            this.TargetDatabase = new System.Data.Entity.Infrastructure.DbConnectionInfo(

     @"Server=(local)\SQLEXPRESS;Database=BankPersistenceModel;Trusted_Connection=True",

     "System.Data.SqlClient");
        }
    }

 

Be careful: changing the domain specific model might come with potential data loss e.g. if you delete a property of a Persistent Object. The migration initializer will notice this and throw an exception unless you set the “AutomaticMigrationDataLossAllowed” property to “true” (see comment in code snippet above).

 

Use the MigrateDatabaseToLatestVersion<T, U> class instead of the CreateDatabaseIfNotExists initializer:

 

System.Data.Entity.Database.SetInitializer<Context>(

  new System.Data.Entity.MigrateDatabaseToLatestVersion<Context, MigrationConfiguration>());

 

Now go ahead and for example add a new property to the Persistent Object “Customer” (e.g. an address property of type string), save the changes and transform the TaslToCodeFirst.tt again. Then run the program again and have a look inside the database where an additional column will be created.

 

 

Using different Providers

To show you that you’re not restricted to use Microsoft’s SQL Server only, here is how one would approach using a MySQL Server as a persistence layer.

 

Download and install MySQL 6.6.4 for .NET which is compatible to the EntityFramework and supports migration database initializers.

 

Add the MySQL Data Provider Factory to the configuration of your appliction (e.g. app.config):

 

<system.data>

  <DbProviderFactories>

    <add name=”MySQL DataProvider”

         invariant=”MySql.Data.MySqlClient”

         description=”.NET Data Provider for MySQL”

         type=”MySql.Data.MySqlClient.MySqlClientFactory,MySql.Data” />

  </DbProviderFactories>

</system.data>

 

Use a proper connection string for the MySql database to create the Context class with and also in the MigrationConfiguration class.

 

Continuation

In the next (and last) part of the blog series on tangible engineering’s support for Model Driven Development we are going to create another T4 template. This template will create a basic user interface based on the domain specific model from the second part of this blog series using the Entity Framework code classes and the SQL Server persistence layer to display and manipulate data.

Twitter Updates