Quantcast
Channel: Entity Framework
Viewing all articles
Browse latest Browse all 10318

Updated Wiki: Custom Conventions

$
0
0

Custom Code First Conventions

Code First includes a set of simple, model-wide behaviors that provide sensible configuration defaults for the parts of your model that have not been explicitly configured using Data Annotations or the Fluent API. These default behaviors are referred to as Conventions. One commonly requested feature is the ability to add your own conventions.

The Custom Conventions feature will let you define your own conventions to provide custom configuration defaults for your model. The heart of this new feature is the conventions interfaces that you use to implement your own custom conventions. These interfaces fall into two main categories: Configuration-based and Model-based.

An easier way to define configuration based conventions is by using Lightweight conventions.

Lightweight conventions

Lightweight conventions are a way to define a convention inside your OnModelCreating event in a similar way to how you would define normal entity mappings with the Fluent API.

To start with we will show a commonly requested example. Some people want to configure EF to set the precision of all decimal properties in their model. With Lightweight Conventions this can be achieved with the following piece of code:

protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(
        entities => entities.Properties()
            .Where(property => property.PropertyType == typeof(decimal))
            .Configure(config => config.Precision = 10));
}
This code creates a convention that tells EF that all properties on all entities should be configured to have a precision of 10.

This can be conceptualized as the “entities” containing a list of all entities in your model. You then use the properties method to say “for all properties on all entities”. The where then filters all properties to only be those that are of type decimal, and finally you call configure.

Configure is where you decide what to do with all the entities and properties that you haven’t filtered out in the preceding method calls.

Note: The configuration that is passed to configure is a flattened representation of all configuration options. If you configure a property that doesn’t make sense for something that you haven’t filtered out then it will do nothing. This means that if you tried to configure all integers to have a precision of 10 then it would be ignored.

Another example of Lightweight Conventions is when you want to define a different primary key convention, in this case we want all properties that end with “Key” to be a primary key.

protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(
        entities => entities.Properties()
            .Where(prop => prop.Name.EndsWith("Key"))
            .Configure(config => config.IsKey()));
}

Configuration-based conventions

The first type of convention is based on reflection and configuration objects and can be created using IConfigurationConvention. The configuration objects used by this type of convention are similar to the Fluent API objects that are typically used when overriding DbContext.OnModelCreating().

class DefaultDateTimeColumnTypeConvention
    : IConfigurationConvention<PropertyInfo, DateTimePropertyConfiguration>
{
    publicvoid Apply(
        PropertyInfo propertyInfo,
        Func<DateTimePropertyConfiguration> configuration)
    {
        if (configuration().ColumnType == null)
        {
            configuration().ColumnType = "datetime2";
        }
    }
}
The interface’s first type parameter can be either of the following.
  • Type
  • PropertyInfo
The second type parameter can be any of the following.
  • ModelConfiguration
  • PropertyConfiguration
    • NavigationPropertyConfiguration
    • PrimitivePropertyConfiguration
      • DateTimePropertyConfiguration
      • DecimalPropertyConfiguration
      • LengthPropertyConfiguration
        • BinaryPropertyConfiguration
        • StringPropertyConfiguration
  • StructuralTypeConfiguration
    • ComplexTypeConfiguration
    • EntityTypeConfiguration
Any combination is valid except for Type and PropertyConfiguration (or one of its derived types) which will result in Apply() never being called. If you specify PropertyInfo and StructuralTypeConfiguration (or one of its derived types) then Apply() will be called with the configuration for the type that the property is defined on.

Model-based conventions

The second type of convention is based on the underlying model metadata. The interfaces used to create these conventions are IEdmConvention, IDbConvention & IDbMappingConvention. This type of convention gives you more control than configuration-based conventions because it allow you to directly manipulate the model metadata that gets used by Entity Framework.

Note: Additional work is also being done to consolidate and improve the model metadata API used by these conventions. For more information, see Work Item 555.

class ModelBasedConvention : IEdmConvention <EdmProperty>
{
    publicvoid Apply(EdmProperty property, EdmModel model)
    {
        if (property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Decimal
            && property.Scale == null)
        {
            property.Scale = 4;
        }
    }
}
These conventions are always applied after the configuration-based conventions. They are applied in order according to their interface type:
  1. IEdmConvention
  2. IDbConvention
  3. IDbMappingConvention

Adding conventions

To enable a custom convention to be applied during model creation, call Add() on DbModelBuilder.Conventions.

protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add<DefaultDateTimeColumnTypeConvention>();
}
The order in which conventions get applied is important. For example, our DefaultDecimalScaleConvention above will have no affect if Scale has already been set; therefore, it must be applied before the built-in DecimalPropertyConvention. AddBefore() and AddAfter() are used to influence a convention’s order.

modelBuilder.Conventions.AddBefore<DecimalPropertyConvention>(
    new DefaultDecimalScaleConvention());
These methods can be used to control the order of lightweight conventions as well.

Viewing all articles
Browse latest Browse all 10318

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>