Daily Archives: May 18, 2011

Quick Look at Reverse Engineer DB into Code First Classes

The Entity Framework team blogged about the EF Power Tools CTP1 today. One of the intriguing features is the ability to reverse engineer an existing database into a set of code first classes.

 

I put it to a *very* quick test since it’s way past my bedtime. Smile

After installing the tool and creating a new class library project, I reverse engineered the following tiny simple database:

image

The tool created a bunch of classes grouped into an Entities folder (from tables and views in my db), a set of fluent api mappings grouped into a Mapping folder and a context class. It also added the EntityFramework.dll for EF 4.1 and System.Data.Entity to the project.

image

 

A quick look at one of the Customer.cs class:

using System;
using System.Collections.Generic;

namespace TestEFPowerToolsCTP1.Entities
{
    public class Customer
    {
        public Customer()
        {
            this.Orders = new List<Order>();
        }

        public int CustomerID { get; set; }
        public string Title { get; set; }
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public string Suffix { get; set; }
        public string CompanyName { get; set; }
        public string SalesPerson { get; set; }
        public string EmailAddress { get; set; }
        public string Phone { get; set; }
        public System.DateTime ModifiedDate { get; set; }
        public byte[] TimeStamp { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
    }
}

The Customer mapping file:

using System;
using System.Data.Entity.ModelConfiguration;
using System.Data.Common;
using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using TestEFPowerToolsCTP1.Entities;

namespace TestEFPowerToolsCTP1.Mapping
{
    public class CustomerMap : EntityTypeConfiguration<Customer>
    {
        public CustomerMap()
        {
            // Primary Key
            this.HasKey(t => t.CustomerID);

            // Properties
            this.Property(t => t.Title)
                .HasMaxLength(8);
                
            this.Property(t => t.FirstName)
                .IsRequired()
                .HasMaxLength(50);
                
            this.Property(t => t.MiddleName)
                .HasMaxLength(50);
                
            this.Property(t => t.LastName)
                .IsRequired()
                .HasMaxLength(50);
                
            this.Property(t => t.Suffix)
                .HasMaxLength(10);
                
            this.Property(t => t.CompanyName)
                .HasMaxLength(128);
                
            this.Property(t => t.SalesPerson)
                .HasMaxLength(256);
                
            this.Property(t => t.EmailAddress)
                .HasMaxLength(50);
                
            this.Property(t => t.Phone)
                .HasMaxLength(25);
                
            this.Property(t => t.TimeStamp)
                .IsRequired()
                .IsFixedLength()
                .HasMaxLength(8);
                
            // Table & Column Mappings
            this.ToTable("Customers");
            this.Property(t => t.CustomerID).HasColumnName("CustomerID");
            this.Property(t => t.Title).HasColumnName("Title");
            this.Property(t => t.FirstName).HasColumnName("FirstName");
            this.Property(t => t.MiddleName).HasColumnName("MiddleName");
            this.Property(t => t.LastName).HasColumnName("LastName");
            this.Property(t => t.Suffix).HasColumnName("Suffix");
            this.Property(t => t.CompanyName).HasColumnName("CompanyName");
            this.Property(t => t.SalesPerson).HasColumnName("SalesPerson");
            this.Property(t => t.EmailAddress).HasColumnName("EmailAddress");
            this.Property(t => t.Phone).HasColumnName("Phone");
            this.Property(t => t.ModifiedDate).HasColumnName("ModifiedDate");
            this.Property(t => t.TimeStamp).HasColumnName("TimeStamp");
        }
    }
}

and the context:

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using TestEFPowerToolsCTP1.Entities;
using TestEFPowerToolsCTP1.Mapping;

namespace TestEFPowerToolsCTP1
{
    public class CustomersContext : DbContext
    {
        static CustomersContext()
        { 
            Database.SetInitializer<CustomersContext>(null);
        }

        public DbSet<Customer> Customers { get; set; }
        public DbSet<LineItem> LineItems { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<sysdiagram> sysdiagrams { get; set; }
        public DbSet<custview> custviews { get; set; }
        public DbSet<vSalesOrderDetail> vSalesOrderDetails { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new LineItemMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new sysdiagramMap());
            modelBuilder.Configurations.Add(new custviewMap());
            modelBuilder.Configurations.Add(new vSalesOrderDetailMap());
        }
    }
}

Very nice!

One of the suggestions in the comments on the team blog post is to be able to select which tables/views get reverse engineered.