14

Using Entity-Framework 6 I'm able to set up the configuration through Fluent Api like this:

public class ApplicationUserConfiguration : EntityTypeConfiguration<ApplicationUser>
{
    public ApplicationUserConfiguration()
    {
        this.HasKey(d => d.Id);
        this.Ignore(d => d.UserId);
    }
}

Source from this question

Using the attribute approach I'm able to know what's the property roles by reflection, but I wonder how can I retrieve these configurations, like Key for example, with Fluent Api approach?

There's no public property from the EntityTypeConfiguration<> class.

Is that possible to get the Key and ForeignKey somehow?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Diego Rafael Souza
  • 5,241
  • 3
  • 23
  • 62

1 Answers1

12

There is a MetadataWorkspace class which provides API to retrieve metadata about storage, model, CLR types and mappings for Entity Framework.

Represents the ADO.NET metadata runtime service component that provides support for retrieving metadata from various sources.

Having an instance of DbContext, you can find its MetadataWorkspace using following code:

var metadataWorkspace = ((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace;

Then you can get item collections which contain different types of models including object model, the conceptual model, the storage (database) model, and the mapping model between the conceptual and storage models.

The following extension methods returns EntityType for given clr type:

using System;
using System.Data.Entity;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Linq;

public static class DbContextExtensions
{
    public static EntityType GetEntityMetadata<TEntity>(this DbContext dbContext)
    {
        if (dbContext == null)
            throw new ArgumentNullException(nameof(dbContext));

        var metadataWorkspace = ((IObjectContextAdapter)dbContext)
            .ObjectContext.MetadataWorkspace;
        var itemCollection = ((ObjectItemCollection)metadataWorkspace
            .GetItemCollection(DataSpace.OSpace));
        var entityType = metadataWorkspace.GetItems<EntityType>(DataSpace.OSpace)
            .Where(e => itemCollection.GetClrType(e) == typeof(TEntity)).FirstOrDefault();

        if (entityType == null)
            throw new Exception($"No entity mapped to CLR type '{typeof(TEntity)}'.");

        return entityType;
    }
}

Then you can use EntityType to extract more information about the model, for example you can find a list of key properties:

var keys = dbcontext.GetEntityMetadata<Category>().KeyProperties.Select(x=>x.Name).ToList();
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 3
    Nice! That's exactly what I needed. Thanks – Diego Rafael Souza Aug 22 '18 at 11:58
  • 2
    Related - This article helped me to understand and to develop the solution: https://www.tabsoverspaces.com/230583-metadataworkspace-in-entity-framework?utm_source=blog.cincura.net – Diego Rafael Souza Aug 23 '18 at 12:32
  • Is `IObjectContextAdapter` still available in .NetCore 2.2? I can't seem to find a reference to System.Data.Entity. – RHarris Dec 19 '19 at 17:43
  • @RHarris The question is tagged with Entity Framework 6. It's not about EF core. – Reza Aghaei Dec 19 '19 at 17:49
  • This didnt work for me. I did the check like this: _context.GetEntityMetadata().Properties["Code"].Nullable, it returned true. I was expecting False for my case as my "Code" property is registered as IsRequired using FluentApi. I did notice that my other non-string properties that are registered as IsRequired, they do return false as expected. Not sure why it wont pick up for strings. Any insight into this would be great. – User123 Sep 21 '22 at 21:53