Monthly Archives: May 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.

Model First, Database First or Code First–Update to Data Points Column

My recent Data Points column in MSDN Magazine (May 2011) provided an overview of the differences between the three workflows for creating an Entity Framework model:

1) Reverse engineer and existing database into an EDMX model

2) Create an EDMX model in the designer and generate a database from that

3) Forego a physical model and use your domain classes along with Entity Framework Code First.

After listing the big differences and discussing pros & cons of the different workflows, I presented a diagram to encapsulate the decision making.

A few days before the article became public, I received an email from a developer asking about how to create a model when he had pre-existing classes and a pre-existing database. The obvious answer (in my mind) was to use Code First. Otherwise, he would have had to try to work out a model that would match his existing classes.

I immediately realized that I did not include that suggestion in the decision tree in the article, so here is that diagram, updated.

The new decisions are in red.

image

I know that even after you’ve said that you prefer a visual designer, I’m still recommending that you don’t use it in this case (point back to code first) but believe me, you’ll most likely be happier in that scenario.

Vermont IT Jobs: .NET Software Engineer, DBA and Architect jobs at Allscripts in Burlington

There are a bunch of dev & database related jobs at Allscripts.com/careers.

 
 
Job Title Requisition Number Area Of Interest City State
Data Conversion Consultant OP7675 Client Services Burlington Vermont
Database Administrator OP8095 Development Burlington Vermont
Interface Analyst OP7090 Client Services Burlington Vermont
Interface Architect OP7674 Client Services Burlington Vermont
Interface Architect OP7680 Client Services Burlington Vermont
Interface Implementation Specialist OP7678 Client Services Burlington Vermont
Interface Implementation Specialist OP7679 Client Services Burlington Vermont
Senior Software Engineer OP8270 Development Burlington Vermont
Upgrade Implementation Consultant OP7928 Professional Burlington Vermont
 

Contact their recruiter:

Joanne Henderson | Corporate Recruiter |Allscripts

www.allscripts.com

http://www.allscripts.com/en/company/careers/opportunities.html

http://www.linkedin.com/in/jhenders