Pages

Sunday, May 4, 2014

Entity First - Code First - Migrations Setup

1. Created two window class project:
  • exposing the domain classes:
  • exposing the DB context classes
2. Created a MVC  4.5.1 project

1. Created two window class projects:
Domain Classes
using System;

namespace FileUpload.DomainClasses
{
    public class Media
    {
        public int Id { get; set; }
        public int MediaTypeId { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Caption { get; set; }
        public string Description { get; set; }
        public string Path { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public DateTime IDate { get; set; }
        public DateTime UDate { get; set; }

        public virtual MediaType MediaType { get; set; }

    }
}


namespace FileUpload.DomainClasses
{
    public class MediaType
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Extension { get; set; }
    }
}


DB Context Class

Reaching the domain class add reference to FileUpload.DominClasses.

Within the constructor, explicitly set connection string name, which will be found within web.config.

using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

namespace FileUpload.DataLayer
{
    public class FileUploadContext : DbContext
    {
        public FileUploadContext()
            : base("name=FileUploadContextDB")
        {

        }
        public DbSet<Media> Medias { get; set; }
        public DbSet<MediaType> MediaTypes { get; set; }
    }
}


Connection String

Within web.config, added two connection strings.


  • FileUploadContext
  • FileUploadContextDB

FileUploadContext is name of the DB context class. If a connection string wasn’t explicitly set within the DB context class constructor, then a connection string with the context class name will be used.

However, the context class above has explicitly set the connection string within the constructor, so the  FileUploadContextDB connection string  is used.

web.config connectionStrings

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="FileUploadContext" connectionString="Data Source=(localdb)\Projects;Initial Catalog=FileUploadContextDB;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False" providerName="System.Data.SqlClient" />
    <add name="FileUploadContextDB" connectionString="Data Source=DEDOGS-PC\DEDOGSSQL;Initial Catalog=FileUploadContextDB;Integrated Security=False;User ID=sa;Password=moclay9330;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False" providerName="System.Data.SqlClient" />
  </connectionStrings>
    <system.web>
      <compilation debug="true" targetFramework="4.5.1" />
      <httpRuntime targetFramework="4.5.1" />
    </system.web>

</configuration>





2. Created a MVC  4.5.1 project

Reaching the, add reference :


  • domain class, to FileUpload.DominClasses.
  • DB context, to FileUpload.DataLayer.

Created a Controller with a View.

namespace FileUpload_MVC.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            using (var context = new FileUploadContext())
            {
                var medias = context.Medias.ToList();

            }
            return View();
        }
    }
}


On the first attempt, when a database hasn’t been setup, asking for the Medias list, Entity Framework will create a database. The database scheme reflects the context class’ names and properties.

image

Influence DB Scheme by Enabling Entity Framework Migrations Feature

Migrations track changes with your C# code.

Within the Package Manager:

1. Select FileUploadDataLayer from Default project dropdown.

pc

2. Type

PM> Enable-Migrations –ContextTypeName FileUploadContext

This will run migrations against the default project creating a Migrations folder in the FileUploadDataLayer project.

image

image

3. Within Configuration.cs, AutomaticMigrationsEnabled is set equal to false. Set AutomaticMigrationsEnabled equal to true. This will allow automatic changes to occur in the database. AutomaticMigrationsEnabled  should only be set true in production or whenever working with beginning stages.

namespace FileUpload.DataLayer.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<FileUpload.DataLayer.FileUploadContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "FileUpload.DataLayer.FileUploadContext";
        }

        protected override void Seed(FileUpload.DataLayer.FileUploadContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}

 

4. Seed method allow automatically populating the database with data. Every time the database is updated it will run the seed method.

protected override void Seed(FileUpload.DataLayer.FileUploadContext context)
{
    context.MediaTypes.AddOrUpdate(mt => mt.Name,
        new MediaType { Name = "JPEG", Extension = "jpg" },
        new MediaType { Name = "GIF", Extension = "gif" },
        new MediaType { Name = "PNG", Extension = "png" }
        );
    context.Medias.AddOrUpdate(r => r.Name,
        new Media { Name = "Kirk", UDate = DateTime.Now, IDate = DateTime.Now, MediaTypeId = 1 },
        new Media { Name = "Kirk", UDate = DateTime.Now, IDate = DateTime.Now, MediaTypeId = 1 },
        new Media { Name = "Kirk", UDate = DateTime.Now, IDate = DateTime.Now, MediaTypeId = 1 }
        );
}

5. Within the Package Manager Console and FileUpload.Datalayer selected as default project, update database with this seed data.

 

PM> Update-Database –Verbose

 

image

 

Migration SQL Script or Update Database are two ways when handling changes when class properties are added or removed.

If AutomaticMigrationsEnabled  is set true, then by just running Update-Database from package manager will handle any scheme changes.

if AutomaticMigrationsEnabled  is set false, then must use a Migration SQL Script. A migration script was created and is located in the Migration folder.

namespace FileUpload.DataLayer.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class InitialCreate : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Media",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        MediaTypeId = c.Int(nullable: false),
                        Name = c.String(),
                        Title = c.String(),
                        Caption = c.String(),
                        Description = c.String(),
                        Path = c.String(),
                        Width = c.Int(nullable: false),
                        Height = c.Int(nullable: false),
                        IDate = c.DateTime(nullable: false),
                        UDate = c.DateTime(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.MediaTypes", t => t.MediaTypeId, cascadeDelete: true)
                .Index(t => t.MediaTypeId);
            
            CreateTable(
                "dbo.MediaTypes",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                        Extension = c.String(),
                    })
                .PrimaryKey(t => t.Id);
            
        }
        
        public override void Down()
        {
            DropForeignKey("dbo.Media", "MediaTypeId", "dbo.MediaTypes");
            DropIndex("dbo.Media", new[] { "MediaTypeId" });
            DropTable("dbo.MediaTypes");
            DropTable("dbo.Media");
        }
    }
}



This post is for the purpose of my notes only.


“I invented nothing new. I simply assembled the discoveries of other men behind whom were centuries of work. Had I worked fifty or ten or even five years before, I would have failed. So it is with every new thing. Progress happens when all the factors that make for it are ready and then it is inevitable. To teach that a comparatively few men are responsible for the greatest forward steps of mankind is the worst sort of nonsense.”


Henry Ford

No comments:

Post a Comment