https://github.com/toreaurstadboss/BulkOperationsEntityFramework
The custom code convention for setting all properties called Key of property type Guid as the key of an entity (table) looks like the following:
GuidKeyConvention.cs
using System;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Reflection;
namespace BulkOperationsEntityFramework.Conventions
{
public class GuidKeyConvention : Convention
{
public GuidKeyConvention()
{
Types().Configure(t =>
{
var keyProperty = t.ClrType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.FirstOrDefault(p => p.PropertyType == typeof(Guid)
&& string.Equals(p.Name, "Key", StringComparison.OrdinalIgnoreCase));
if (keyProperty != null)
{
t.HasKey(keyProperty);
}
});
}
}
}
The custom code convention can then be added in the OnModelCreating method shown below :
ApplicationDbContext.cs
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasKey(u => u.Id);
modelBuilder.Entity<User>().Property(u => u.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Properties<string>().Configure(p => p.HasMaxLength(255)); // Set max length for all string properties
modelBuilder.Conventions.Add(new GuidKeyConvention());
//more code
}
As shown above, a custom convention inherits from the System.Data.Entity.ModelConfiguration.Conventions.Convention class. The behavior of the custom code convention is set up in the constructor of the custom code convention. It is not overriding any methods, instead it is making use over inherited public methods Types() or Properties() or PropertiesSession.cs
using System;
namespace BulkOperationsEntityFramework.Models
{
public class Session
{
public Guid Key { get; set; } // Primary key by convention
public DateTime CreatedAt { get; set; }
public DateTime? ExpiresAt { get; set; }
public string IpAddress { get; set; }
public string UserAgent { get; set; }
}
}
Adding this custom code convention, the following database migration is then added and shows that the property (field/column) called Key of type Guid.
namespace BulkOperationsEntityFramework.Migrations
{
using System.Data.Entity.Migrations;
public partial class Sessions : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Sessions",
c => new
{
Key = c.Guid(nullable: false),
CreatedAt = c.DateTime(nullable: false),
ExpiresAt = c.DateTime(),
IpAddress = c.String(maxLength: 255),
UserAgent = c.String(maxLength: 255),
})
.PrimaryKey(t => t.Key);
}
public override void Down()
{
DropTable("dbo.Sessions");
}
}
}
As shown in the database migration, the primary key is set to the field Key, which means that the field (property/column) Key is set as the primary key.
It is of course easier to just attribute the property Key with the Key attribute or set up the primary key in the OnModelConfiguring (Fluent API).
Custom code conventions are best in use when you make a custom code convention that saves a lot of setup where you have a large data model and want to standardize code conventions, this sample just is a demonstration of how
such a custom code convention can be created by inheriting the Convention class in the namespace System.Data.Entity.ModelConfiguration.Conventions.
In the previous article, a custom code convention encapsulated in a custom marker attribute and wiring up the logic via helper extension methods. Instead of inheriting from the Convention class, the wiring up of Schema attribute shown in previous article
could be more standardized in this way.
Such a SchemaConvention could be set up like this instead, inheriting Convention class.
SchemaConvention.cs
using BulkOperationsEntityFramework.Attributes;
using System.Data.Entity.Infrastructure.Pluralization;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Reflection;
namespace BulkOperationsEntityFramework.Conventions
{
public class SchemaConvention : Convention
{
public SchemaConvention()
{
var pluralizer = new EnglishPluralizationService();
Types().Configure(c =>
{
var schemaAttr = c.ClrType.GetCustomAttribute<SchemaAttribute>(false);
var tableName = pluralizer.Pluralize(c.ClrType.Name);
if (schemaAttr != null && !string.IsNullOrEmpty(schemaAttr.SchemaName))
{
c.ToTable(tableName, schemaAttr.SchemaName ?? "dbo");
}
else
{
c.ToTable(tableName);
}
});
}
}
}