One of the most popular posts on my blog has been EF6.1 Mapping Between Types & Tables. Someone asked me this week about getting the property/column mapping in addition to the type/table mapping. There isn’t a whole lot to say (other than the code is horrible and this will look a whole lot better in EF7), so here is the code.
using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Core.Mapping; using System.Data.Entity.Core.Metadata.Edm; using System.Data.Entity.Infrastructure; using System.Linq; namespace MappingDemo { class Program { static void Main(string[] args) { using (var db = new BlogContext()) { Console.WriteLine("Blog.BlogId maps to: {0}", GetColumnName(typeof(Blog), nameof(Blog.BlogId), db)); Console.WriteLine("Post.Body maps to: {0}", GetColumnName(typeof(Post), nameof(Post.Body), db)); } } public static string GetColumnName(Type type, string propertyName, DbContext context) { var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace; // Get the part of the model that contains info about the actual CLR types var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace)); // Get the entity type from the model that maps to the CLR type var entityType = metadata .GetItems<EntityType>(DataSpace.OSpace) .Single(e => objectItemCollection.GetClrType(e) == type); // Get the entity set that uses this entity type var entitySet = metadata .GetItems<EntityContainer>(DataSpace.CSpace) .Single() .EntitySets .Single(s => s.ElementType.Name == entityType.Name); // Find the mapping between conceptual and storage model for this entity set var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace) .Single() .EntitySetMappings .Single(s => s.EntitySet == entitySet); // Find the storage entity set (table) that the entity is mapped var tableEntitySet = mapping .EntityTypeMappings.Single() .Fragments.Single() .StoreEntitySet; // Return the table name from the storage entity set var tableName = tableEntitySet.MetadataProperties["Table"].Value ?? tableEntitySet.Name; // Find the storage property (column) that the property is mapped var columnName = mapping .EntityTypeMappings.Single() .Fragments.Single() .PropertyMappings .OfType<ScalarPropertyMapping>() .Single(m => m.Property.Name == propertyName) .Column .Name; return tableName + "." + columnName; } } public class BlogContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .ToTable("t_blog"); modelBuilder.Entity<Blog>() .Property(b => b.BlogId) .HasColumnName("blog_id"); modelBuilder.Entity<Post>() .ToTable("t_post"); modelBuilder.Entity<Post>() .Property(b => b.Body) .HasColumnName("post_body"); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Body { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } } }