Entity Developer – EF Code First DbContext Template

Posted by on May 17th, 2011

Note: To use the template “DbContext”, Entity Framework 4.1 and Entity Framework 4.0 must be installed on your computer.

April 2011 saw the release of a new version of Entity Framework 4.1 that supports fluent mapping and DbContext API. The latest version of Devart Entity Developer is extended with the DbContext template that enables the use of new features in EF v4.1. Initially, fluent mapping was intended to be used in the Code-First (Code Only) approach. However, thanks to our new template, fluent mapping can now be used not only in the Code-First approach, but in the Database-First/Model-First approaches as well.

DbContext Template Properties Screenshot

DbContext API

New DbContext API is the major novelty in Entity Framework 4.1. Being an ObjectContext wrapper, this is a more lightweight alternative to the use of ObjectContext in EFv1/EFv4. DbContext can be used both with fluent mapping and XML-mapping.

Here we will not delve into details about the new API. For more information on DbContext, use the MSDN documentation and a number of publications on the ADO.NET team blog.

In the Entity Developer template, you can define the following options of DbContext configuration:

  • AutoDetectChangesEnabled – Determines whether the automatic detection of changes in the configuration is enabled. The default value is true.
  • ProxyCreationEnabled – Determines whether the framework will create instances of dynamically generated proxy classes whenever it creates an instance of an entity type. Note that even if proxy creation is enabled, proxy instances will only be created for entity types that meet the requirements for being proxied. The default value is true.
  • ValidateOnSaveEnabled – Determines if tracked entities are validated automatically when SaveChanges() is called. The default value is true.

Fluent mapping

The  DbContext template of  Entity Developer contains the FluentMapping option that determines, if the Entity Framework code only mapping is included into the generated code or XML mapping from the edml file is used. The default value is false, which means that XML mapping is used.

Alternatively, if FluentMapping is set to True, fluent mapping is generated. This process generates column facets, the primary key for tables, foreign keys, complex types, taking into account inheritance of all three types (TPH, TPT, and TPC) and simple entity splitting.

Below is a brief example of generated mapping for a simple model consisting of three classes with Table Per Hierarchy (TPH):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    #region TphRoot

    modelBuilder.Entity<TphRoot>()
        .HasKey(p => new { p.Id })
        .Map(tph => {
            tph.Requires("ConditionColumn").HasValue("r");
            tph.ToTable("TPH_TABLE", "SCOTT");
        });
    // Properties:
    modelBuilder.Entity<TphRoot>()
        .Property(p => p.Id)
            .IsRequired()
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
            .HasColumnType("int");
    modelBuilder.Entity<TphRoot>()
        .Property(p => p.Name)
            .HasMaxLength(16)
            .HasColumnType("VARCHAR2");

    #endregion

    #region TphChildA

    modelBuilder.Entity<TphChildA>()
        .Map(tph => {
            tph.Requires("ConditionColumn").HasValue("a");
            tph.ToTable("TPH_TABLE", "SCOTT");
        });
    // Property:
    modelBuilder.Entity<TphChildA>()
        .Property(p => p.PropertyA)
            .HasMaxLength(120)
            .HasColumnType("NVARCHAR2");

    #endregion

    #region TphChildB

    modelBuilder.Entity<TphChildB>()
        .Map(tph => {
            tph.Requires("ConditionColumn").HasValue("b");
            tph.ToTable("TPH_TABLE", "SCOTT");
        });
    // Property:
    modelBuilder.Entity<TphChildB>()
        .Property(p => p.PropertyB)
            .HasColumnType("BLOB");

    #endregion
}

Code-First Configuration Conventions

The DbContext template of Entity Developer contains the DisabledConventions option that allows you to disable the configuration conventions of Code-First.

The Entity Framework Code-First list of conventions is too large, that’s why our DisabledConventions list does not include various attribute conventions (for example, ColumnAttributeConvention, ComplexTypeAttributeConvention and others) that the user normally does not need to disable.

One of the most useful conventions that gets disabled more often than not is IncludeMetadataConvention. This convention determines whether it is necessary to create / use / delete the “EdmMetadata” table that stores the model hash which is used to check whether the model has changed since the database was created from it.

The full list of code-first configuration conventions and their descriptions are published on MSDN.

Simultaneous Use of Several Databases

Previously, there was only one way of creating an EF-application that uses several databases, for example, Oracle + Microsoft SQL Server. First, we created several EF-models, one model per DBMS. Then we put the following resources into the application: one CSDL, one MSL and one SSDL per each database. Then, depending on the server, we changed the connection string that specified different resources.

Fluent mapping is a real alternative to the approach involving several EF-models and different SSDL-resources. Now it is enough to create one EF-model in the Entity Developer application using the Database-First or Model-First approach. Following that, we remove the standard code generation template and enable the DbContext template. In the template properties, we need to set FluentMapping=True and DatabaseIndependent=True.

The DatabaseIndependent property determines whether the database-specific data type is set when fluent mapping is generated. If DatabaseIndependent is set by default to False, the following code is generated:

modelBuilder.Entity()
        .Property(p => p.Dname)
            .HasColumnName("DNAME")
            .HasMaxLength(14)
            .HasColumnType("VARCHAR2");
    modelBuilder.Entity()
        .Property(p => p.NCharField)
            .HasColumnName("NCHAR_FIELD")
            .HasMaxLength(16)
            .HasColumnType("NCHAR");

When set to True:

modelBuilder.Entity()
        .Property(p => p.Dname)
            .HasColumnName("DNAME")
            .HasMaxLength(14)
            .IsUnicode(false);
    modelBuilder.Entity()
        .Property(p => p.NCharField)
            .HasColumnName("NCHAR_FIELD")
            .HasMaxLength(16)
            .IsFixedLength()
            .IsUnicode(true);

In the latter case, the EF-provider is responsible for the selection of a particular database-specific data type. The provider can be defined in several ways. For more information on how to define a provider-specific connection, see Entity Framework Code-First support for Oracle, MySQL, PostgreSQL and SQLite.

Fluent Mapping Limitations

When using the Code-First development approach, you should remember that fluent mapping in Entity Framework 4.1 does not fully support all capabilities provided by conventional XML-mapping. Thus, within fluent mapping, you can no longer use:

  • stored procedures;
  • compiled queries;
  • complex entity splitting.

See also the following article on MSDN: What’s Not Supported (Entity Framework 4.1).
Besides, when using the Code-First development approach, note that when dynamic database creation is used, you cannot influence the name generation mechanism for:

  • primary keys;
  • foreign keys;
  • indexes;
  • constraints;
  • sequences and triggers (Oracle only).

See also

For more information on how to use fluent mapping (code first) in our EF-providers, see Entity Framework Code-First support for Oracle, MySQL, PostgreSQL and SQLite. You can also download samples there.

In the latest version of our EF-providers we have implemented the possibility to more flexibly configure the process of database creation and dropping. The specifics of configuration is described in the article New Features of Entity Framework Support in dotConnect Providers.

Comments are closed.


Devart Blog