Friday, December 28, 2012

Entity Framework Fluent API Article's Sample Code

Related Article : How to Use Entity Framework Fluent API ?

Project Tree

Project Tree


SchoolEntities.cs


using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace EFFluventAPI.Models
{
  public class SchoolEntities : DbContext
  {
    public DbSet<Course> Courses { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<Instructor> Instructors { get; set; }
    public DbSet<OfficeAssignment> OfficeAssignments { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      //Configure Code First to ignore PluralizingTableName convention
      //If you keep this convention then the generated tables
      //will have pluralized names
      modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

      modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorId);

      modelBuilder.Entity<Department>()
            .HasKey(t => new { t.DepartmentId, t.Name });

      modelBuilder.Entity<Department>()
            .Property(t => t.DepartmentId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

      modelBuilder.Entity<Department>().Property(t => t.Name).HasMaxLength(50);

      modelBuilder.Entity<Department>().Property(t => t.Name).IsRequired();

      modelBuilder.Entity<Department>().Ignore(t => t.Budget);

      modelBuilder.Entity<Department>()
             .Property(t => t.Name).HasColumnName("DepartmentName");

      modelBuilder.Entity<Course>()
             .HasRequired(c => c.Department)
             .WithMany(t => t.Courses).Map(m => m.MapKey("ChangedDepartmentId"));

      modelBuilder.Entity<Department>().Property(t => t.Name).IsUnicode(false);

      modelBuilder.Entity<Department>()
            .Property(p => p.Name).HasColumnType("varchar");

      modelBuilder.ComplexType<Details>()
            .Property(t => t.Location).HasMaxLength(20);

      modelBuilder.Entity<OnsiteCourse>()
           .Property(t => t.Details.Location).HasMaxLength(20);

      modelBuilder.Entity<OfficeAssignment>()
             .Property(t => t.Timestamp).IsConcurrencyToken(); 
            
       modelBuilder.Entity<OfficeAssignment>()
            .Property(t => t.Timestamp).IsRowVersion();

        }
    }
}



Course.cs

using System.Collections.Generic;

namespace EFFluventAPI.Models
{
    public class Course
    {
        public Course()
        {
            this.Instructors = new HashSet<Instructor>();
        }

        // Primary key
        public int CourseId { get; set; }

        public string Title { get; set; }
        public int Credits { get; set; }

        // Foreign key
        public int DepartmentId { get; set; }

        // Navigation properties
        public virtual Department Department { get; set; }
        public virtual ICollection<Instructor> Instructors { get; private set; }
    }
}

Department.cs

using System.Collections.Generic;

namespace EFFluventAPI.Models
{
    public class Department
    {
        public Department()
        {
            this.Courses = new HashSet<Course>();
        }

        // Primary key
        public int DepartmentId { get; set; }
        public string Name { get; set; }
        public decimal Budget { get; set; }
        public System.DateTime StartDate { get; set; }
        public int? Administrator { get; set; }

        // Navigation property
        public virtual ICollection<Course> Courses { get; private set; }
    }
}

Instructor.cs

using System;
using System.Collections.Generic;

namespace EFFluventAPI.Models
{
    public class Instructor
    {
        public Instructor()
        {
            this.Courses = new List<Course>();
        }

        // Primary key
        public int InstructorId { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public DateTime HireDate { get; set; }

        // Navigation properties
        public virtual ICollection<Course> Courses { get; private set; }
    }
}


OfficeAssignment.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace EFFluventAPI.Models
{
    public class OfficeAssignment
    {
        public Int32 InstructorId { get; set; }

        public string Location { get; set; }

        public Byte[] Timestamp { get; set; }

        // Navigation property
        public virtual Instructor Instructor { get; set; }
    }
}

Details.cs


using System;

namespace EFFluventAPI.Models
{
    public class Details
    {
        public DateTime Time { get; set; }
        public string Location { get; set; }
        public string Days { get; set; }
    }
}

OnsiteCourse.cs

namespace EFFluventAPI.Models
{
    public class OnsiteCourse : Course
    {
        public OnsiteCourse()
        {
            Details = new Details();
        }

        public Details Details { get; set; }
    }
}

Related Article : How to Use Entity Framework Fluent API ?

How to Use Entity Framework Fluent API ?

How to Change Entity Framework Default Conventions, when Mapping Data ?

There are 3 ways.

1. Entity Framework Fluent API

2. Fluent Validation
       - Validation Library for .NET
       - This uses a fluent interface and lambda expressions for building validation rules
          for your business objects

3. Data Annotations 
          - Annotations only cover a subset of the Fluent Validation functionality


Entity Framework Fluent API

       
What is Entity Framework Fluent API ?
  • When working with Entity Framework Code First the default behavior is to map your POCO classes to tables using a set of conventions baked into Entity Framework
  • Sometimes, however you cannot or do not want to follow those conventions and need to map entities to something other than what the conventions dictate
  • For such a scenario you can use Fluent API
  • Can be Used Only with Code First Development
  • This is used to define the mapping between your objects and the database

What Does Fluent API  do ?
  • The Code First Fluent API is most commonly accessed by overriding the OnModelCreating method on your derived DbContext class

Which Tasks can be Achieved by using Fluent API ?

1. Property Mapping

2. Type Mapping

3. Configuring Relationships

On This Article I will explain Property Mapping with Fluent API.  

Article's Sample Code Here

1. Property Mapping

    - is used to configure attributes for each property belonging to an entity or complex type
    - is used to obtain a configuration object for a given property
    - the options on the configuration object are specific to the type being configured
                 e.g. IsUnicode is available only on string properties 

  • How to Configure a Primary Key ?
          - The HasKey method is used to configure the InstructorID primary key on the
             OfficeAssignment type

       modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorId);

  • How to Configure a Composite Primary Key ?
         - DepartmentId and Name properties to be the composite primary key of the
           Department type

      modelBuilder.Entity<Department>()
           .HasKey(t => new { t.DepartmentId, t.Name });

  • How to Switch off Identity for Numeric Primary Keys ?
         - DepartmentId property value will not be generated by the database

      modelBuilder.Entity<Department>()
          .Property(t => t.DepartmentId)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

  • How to Specify the Maximum Length on a Property ?
         - Name property should be no longer than 50 characters

         - If you make the value longer than 50 characters, you will get a 
            DbEntityValidationException exception

         - If Code First creates a database from this model it will also set the
            maximum length of the Name column to 50 characters 

      modelBuilder.Entity<Department>().Property(t => t.Name).HasMaxLength(50);

  • How to Configure the Property to be Required ?
         - Name property is required

         - If you do not specify the Name, you will get a 
            DbEntityValidationException exception

         - If Code First creates a database from this model then the column used to store
            this property will be non-nullable

      modelBuilder.Entity<Department>().Property(t => t.Name).IsRequired(); 

  • How to Specify Not to Map a CLR Property to a Column in the Database ?

      modelBuilder.Entity<Department>().Ignore(t => t.Budget);

  • How to Map a CLR Property to a Specific Column in the Database ?

          - Maps the Name CLR property to the DepartmentName database column

       modelBuilder.Entity<Department>()
                .Property(t => t.Name)
                .HasColumnName("DepartmentName");

  • How to Rename a Foreign Key That Is Not Defined in the Model ?
          - If you choose not to define a foreign key on a CLR type,
          - But want to specify what name it should have in the database

       modelBuilder.Entity<Course>()
          .HasRequired(c => c.Department)
          .WithMany(t => t.Courses)
          .Map(m => m.MapKey("ChangedDepartmentId"));

  • How to Configure whether a String Property Supports Unicode Content ?
          - By default strings are Unicode (nvarchar in SQL Server)
          - You can use the IsUnicode method to specify that a string should be of varchar type

      modelBuilder.Entity<Department>().Property(t => t.Name).IsUnicode(false);

  • How to Configure the Data Type of a Database Column ?
         - The HasColumnType method enables mapping to different representations
            of the same basic type

         - Using this method does not enable you to perform any conversion
            of the data at run time

         - Note that : IsUnicode is the preferred way of setting columns to varchar,
            as it is database agnostic

     modelBuilder.Entity<Department>()
                 .Property(p => p.Name)
                 .HasColumnType("varchar");

  • How to Configure Properties on a Complex Type ?

         Way 1 : You can call Property on ComplexTypeConfiguration

       modelBuilder.ComplexType<Details>()
                   .Property(t => t.Location)
                   .HasMaxLength(20);

        Way 2 : You can also use the dot notation to access a property of a complex type

       modelBuilder.Entity<OnsiteCourse>()
            .Property(t => t.Details.Location)
            .HasMaxLength(20);

  • How to Configure a Property to Be Used as an Optimistic Concurrency Token ?

       Way 1 : You can use either the ConcurrencyCheck attribute
                     or the IsConcurrencyToken method

      modelBuilder.Entity<OfficeAssignment>()
                  .Property(t => t.Timestamp)
                  .IsConcurrencyToken();

      Way 2 : You can also use the IsRowVersion method

     modelBuilder.Entity<OfficeAssignment>()
                 .Property(t => t.Timestamp)
                 .IsRowVersion();
Conclusion
  • You can use Fluent API with Code First development, when you want to override the default conventions maintained by the Entity Framework
  • I will explain Type Mapping and Configuring Relationships with my future Blog Post
  • So Try This and Enjoy it

I hope this helps to You.Comments and feedback greatly appreciated.

Happy Coding

Articles You Might Like

Stay Tuned: I'll be Back with Type Mapping and Configuring Relationships

Monday, December 17, 2012

How to Use Asp.Net MVC Routing Debugger Visualizer ?

What is MVC Routing Debugger Visualizer ?
  • It's an Extension for Visual Studio 2010
  • It Displays the Matched Route Data and Data Tokens of All Defined Routes in your web application
  • It's a Free Product

What is the Basic Requirement Needed for Run MVC Routing Debugger ?
  • Microsoft Visual Studio 2010 Any Edition Except Express Editions 

How to Install MVC Routing Debugger ?

Step 1. Open Visual Studio 2010

Step 2. Click  Tools  ---> Extension Manager

Extension Manager


Step 3. Click "Online Gallery" Button

Online Gallery


Step 4. Type "ASP.NET MVC Routing" inside the Search box

ASP.NET MVC Routing


Step 5. Click "Download" Button

Download


Step 6. Click "Install" Button

Install


Step 7. Click "Restart Now" Button for Restart Visual Studio 2010

Restart Now


That's It.You're Done.


How to Use MVC Routing Debugger ?

Step 1. Run Visual Studio 2010

Step 2. Open Your Asp.Net MVC Project

Step 3. Go to Your Action Method Which You Want to Find Route Details

Step 4. Set a Brake Point on it (Debug your Action Method)

Set a Brake Point

Step 5. Run Your Application

Step 6. When It Hits Your Brake Point , Open the "Watch Window"

Watch Window


Step 7. Add a New Watch Row for "System.Web.Routing.RouteTable.Routes"

New Watch Row


Step 8. Click on the "Magnifying Glass Icon" at the Right Side of the Value field on the
            New Watch Row

Magnifying Glass Icon


Step 9. The "MVC Routing Debugger Visualizer" should be Opened

MVC Routing Debugger Visualizer

  • You can see the Current URL in the Request Url Field
  • Grid of Currently-Defined Routes below that
  • Routes that Match the URL are Highlighted
  • Route Data and Data Tokens Grids are also Showing on the Right side

This is my Global.asax.cs

public static void RegisterRoutes(RouteCollection routes)
 {
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

  routes.MapRoute(
   "Default", // Route name
   "{controller}/{action}/{id}", // URL with parameters
   new { controller ="Home",action ="Index",id =UrlParameter.Optional }//defaults
                 );
  }

How to Change the Value in Request Url ?
  • Type the Request Url (e.g. ~/ShoppingCart)
  • Click "Match Routes" Buttons

Match Routes



That's It.You're Done.


Do You need to Know More Details ?
  • MVC Routing Debugger Visualizer Home

Conclusion
  • It's a very simple Tool for Use and Configure
  • It's running only on Debugger mode
  • When we're having route related issues, this is a tool for debug those issues
  • So Try This and Enjoy it

I hope this helps to You.Comments and feedback greatly appreciated.

Happy Coding


Tools for Visual Studio 2010

Monday, December 10, 2012

How to Improve Performance of Entity Framework Query ?

What is an Entity Framework ( EF ) ?
  • Entity Framework is an Object Relational Mapper (ORM)
  • It basically generates business objects and entities according to the database tables
  • Performing basic CRUD (Create, Read, Update, Delete) operations
  • Easily managing "1 to 1", "1 to many", and "many to many" relationships
  • Ability to have Inheritance relationships between entities

Entity Framework Architecture as below :


Entity Framework Architecture

Cold vs. Warm Query Execution

What is a Cold Query Execution ?
  • The very first time any query is made against a given model ,
  • The Entity Framework does a lot of work behind the scenes to load and validate the model
  • We frequently refer to this first query as a "Cold" query

First Query Execution ( Cold query ) Performance is Like below :

First Query Execution ( Cold query )


Second Query Execution (Warm query ) Performance is Like below :

Second Query Execution (Warm query )


How to Improve Performance of First Query Execution ?
  • For that We have to Remove Cost of View Generation

What is View Generation ?
  • In order to understand what view generation is, we must first understand what “Mapping Views” are :

            What are Mapping Views ?

                     # Mapping Views are executable representations of the transformations
                         specified in the  mapping for each entity set and association

            There are 2 types of Mapping Views exist
                               
                1. Query Views
                         - These represent the Transformation necessary to go from the
                            database schema to the  conceptual schema

               2. Update Views
                        - These represent the Transformation necessary to go from the
                           conceptual schema to the database schema
        
  • The process of computing these views based on the specification of the mapping is what we call View Generation
  • View Generation can either take place dynamically when a model is loaded (run timeor at build time (compile time)
  • Default is a Run Time (that's why first query is very slow)
  • When Views are Generated, they are also Validated
  • From a performance standpoint, the Vast Majority of the cost of View Generation is actually the Validation of the Views
  • Which ensures that the connections between the Entities make sense and have the correct Cardinality for all the supported operations

What are the Factors that Affect View Generation Performance ?
  • Model size -  Referring to the number of entities and the amount of associations between these entities
  • Model complexity - Specifically inheritance involving a large number of types
  • Using Independent Associations, instead of Foreign Key Associations (will explain this in a separate blog post)

How to Use Pre-Generated Views to Decrease Model Load Time ?
  • We can use T4 Templates for Create Pre-Generated Views
  • Then View Generation is happened in Compile Time

What is a T4 ?
  • Text Template Transformation Toolkit
  • T4 is a general-purpose Templating Engine you can use to generate C# code, Visual Basic code, XML, HTML, or text of any kind

How to Use T4 For Generate Views ?

Here I am using VS 2010,C# and EF 4.1 with Code First Approach as Technologies

Step 1 : First you need to Download the Templates
              # Right click on your project's Models Folder (where, DbContext derived class exist)
              # Select Add -> New Item Like below
         
New Item


 Step 2 : # In the Add New Item dialog go to “Online Templates”
              # Then Give "EF Views" as Search Condition
              # After that Select "EF CodeFirst View Generation T4 Template for C#" Like below


EF CodeFirst View Generation T4 Template for C#


Step 3 : # In the above Step 2 Change the Name of the file at the bottom to {Context}.Views.tt
             # Where {Context} is the Name of the Class Derived from DbContext you want to
                 create Pre-Generated Views for. 


In my scenario it's MusicStoreEntities.Views.tt

B'cos my DbContext derived class in Models Folder as below

using System.Data.Entity;

namespace MvcMusicStore.Models
{
    public class MusicStoreEntities : DbContext
    {
        public DbSet<Album> Albums { getset; }
        public DbSet<Genre> Genres { getset; }
        public DbSet<Artist> Artists { getset; }
        public DbSet<Cart> Carts { getset; }
        public DbSet<Order> Orders { getset; }
        public DbSet<OrderDetail> OrderDetails { getset; }
    }
}

Step 4 : Install Template for First Time


Install Template for First Time

Step 5 : Then Finish the Template Installation by clicking OK Button

OK


What If You have already installed "EF CodeFirst View Generation T4 Template for C#" ?

  • Then You can Bypass Step 2,Step 4 & Step 5's Screens with below one
Bypass Step 2,Step 4 & Step 5's Screens


What is a Final Look of  T4 - Generated Views Inside a Project ?

Final Look of  T4 - Generated Views


Conclusion
  • By Creating Pre-Generated Views You can get More Than 4 ,5 Times Performance Boost for Your First Query Execution
  • This is a Big Difference when You're considering a Large Domain Models
  • So Try This and Enjoy the Performance Boost

I hope this helps to You.Comments and feedback greatly appreciated.

Happy Coding


Entity Framework Articles