Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to view Entity Framework Code First's column mappings at runtime?

I'm trying to write an add-on to Entity Framework Code First and I need a way to get the configuration of the model columns at run time. For example, this is the code setup on OnModelCreating by the DbModelBuilder:

builder.Entity<NwdEmployee>()
    .Property(n => n.ReportsToID).HasColumnName("ReportsTo");

Once this is done, EntityFramework knows that my property's name is different to the column name in the table, but how can I find that the string "ReportsTo" relates to ReportsToID myself at runtime? Ideally, I'm trying to write a method such as a following:

public string GetMappedColumnName<TFrom>(DbContext context, 
    Func<TFrom, object> selector);

Which would be used like:

string mappedColumnName = GetMappedColumnName<NwdEmployee>(context, 
    x => x.ReportsToID);

I just don't know where to find the mapped column names within the DbContext. Are they even accessible?

like image 231
djdd87 Avatar asked Oct 09 '22 15:10

djdd87


1 Answers

Theoretically yes. Practically I'm not sure because with simple test I wasn't able to get those information at runtime - I see them in debugger but I cannot get them because the type I need to use is internal in entity framework.

The theory. All mapping information are available at runtime but not through reflection. They are stored in the instance on MetadataWorkspace class which was definitely not designed for direct usage because every interaction with this class demands some time spend in debugger before you find how to get data you need. This data are not accessible through DbContext API. You must convert DbContext back to ObjectContext and access the MetadataWorkspace.

ObjectContext objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
GlobalItem storageMapping = objContext.MetadataWorkspace.GetItem<GlobalItem>("NameOfYourContextClass", DataSpace.CSSpace);

Now storageMapping is instance of System.Data.Mapping.StorageEntityContainerMapping class which is internal. As I understand it this class should be runtime representation of MSL = mapping between storage and conceptual model.

If you use debugger you can explore the instance and you will find information about mapping between properties and columns (its quite deep nested) so you can also use reflection to get them but it is reflection on non public interface of classes you don't own so any .NET framework patch / fix / update can break your application.

like image 174
Ladislav Mrnka Avatar answered Oct 13 '22 10:10

Ladislav Mrnka